diff options
| author | Dmitry Antipov | 2014-05-15 18:59:02 +0400 |
|---|---|---|
| committer | Dmitry Antipov | 2014-05-15 18:59:02 +0400 |
| commit | ddc30c996a3d14e0163df6946ba96c9bcf73bd2f (patch) | |
| tree | 6c0a2fafa8a124e0c6e12174321dc012226bb7a9 | |
| parent | 92491099f710794ee2be60721fae50d68c5ca162 (diff) | |
| download | emacs-ddc30c996a3d14e0163df6946ba96c9bcf73bd2f.tar.gz emacs-ddc30c996a3d14e0163df6946ba96c9bcf73bd2f.zip | |
* src/fns.c (Fnreverse): Allow vectors and bool vectors.
* doc/lispref/lists.texi (Building Cons Cells and Lists): Remove
description of `nreverse' and generalize it...
* doc/lispref/sequences.texi (Sequences): ...for sequences here.
* tests/automated/fns-tests.el (fns-tests-nreverse)
(fns-tests-nreverse-bool-vector): New tests.
| -rw-r--r-- | doc/lispref/ChangeLog | 2 | ||||
| -rw-r--r-- | doc/lispref/lists.texi | 52 | ||||
| -rw-r--r-- | doc/lispref/sequences.texi | 69 | ||||
| -rw-r--r-- | src/ChangeLog | 1 | ||||
| -rw-r--r-- | src/fns.c | 60 | ||||
| -rw-r--r-- | test/ChangeLog | 2 | ||||
| -rw-r--r-- | test/automated/fns-tests.el | 32 |
7 files changed, 150 insertions, 68 deletions
diff --git a/doc/lispref/ChangeLog b/doc/lispref/ChangeLog index d5fe02d2398..7d85e4059c9 100644 --- a/doc/lispref/ChangeLog +++ b/doc/lispref/ChangeLog | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | 2014-05-15 Dmitry Antipov <dmantipov@yandex.ru> | 1 | 2014-05-15 Dmitry Antipov <dmantipov@yandex.ru> |
| 2 | 2 | ||
| 3 | * lists.texi (Building Cons Cells and Lists): Remove | 3 | * lists.texi (Building Cons Cells and Lists): Remove |
| 4 | description of `reverse' and generalize it... | 4 | description of `reverse' and `'nreverse' to generalize them... |
| 5 | * sequences.texi (Sequences): ...for sequences here. | 5 | * sequences.texi (Sequences): ...for sequences here. |
| 6 | 6 | ||
| 7 | 2014-05-14 Glenn Morris <rgm@gnu.org> | 7 | 2014-05-14 Glenn Morris <rgm@gnu.org> |
diff --git a/doc/lispref/lists.texi b/doc/lispref/lists.texi index 882dd440491..f724d5bd902 100644 --- a/doc/lispref/lists.texi +++ b/doc/lispref/lists.texi | |||
| @@ -1124,58 +1124,6 @@ each time you run it! Here is what happens: | |||
| 1124 | @end smallexample | 1124 | @end smallexample |
| 1125 | @end defun | 1125 | @end defun |
| 1126 | 1126 | ||
| 1127 | @defun nreverse list | ||
| 1128 | @cindex reversing a list | ||
| 1129 | This function reverses the order of the elements of @var{list}. | ||
| 1130 | Unlike @code{reverse}, @code{nreverse} alters its argument by reversing | ||
| 1131 | the @sc{cdr}s in the cons cells forming the list. The cons cell that | ||
| 1132 | used to be the last one in @var{list} becomes the first cons cell of the | ||
| 1133 | value. | ||
| 1134 | |||
| 1135 | For example: | ||
| 1136 | |||
| 1137 | @example | ||
| 1138 | @group | ||
| 1139 | (setq x '(a b c)) | ||
| 1140 | @result{} (a b c) | ||
| 1141 | @end group | ||
| 1142 | @group | ||
| 1143 | x | ||
| 1144 | @result{} (a b c) | ||
| 1145 | (nreverse x) | ||
| 1146 | @result{} (c b a) | ||
| 1147 | @end group | ||
| 1148 | @group | ||
| 1149 | ;; @r{The cons cell that was first is now last.} | ||
| 1150 | x | ||
| 1151 | @result{} (a) | ||
| 1152 | @end group | ||
| 1153 | @end example | ||
| 1154 | |||
| 1155 | To avoid confusion, we usually store the result of @code{nreverse} | ||
| 1156 | back in the same variable which held the original list: | ||
| 1157 | |||
| 1158 | @example | ||
| 1159 | (setq x (nreverse x)) | ||
| 1160 | @end example | ||
| 1161 | |||
| 1162 | Here is the @code{nreverse} of our favorite example, @code{(a b c)}, | ||
| 1163 | presented graphically: | ||
| 1164 | |||
| 1165 | @smallexample | ||
| 1166 | @group | ||
| 1167 | @r{Original list head:} @r{Reversed list:} | ||
| 1168 | ------------- ------------- ------------ | ||
| 1169 | | car | cdr | | car | cdr | | car | cdr | | ||
| 1170 | | a | nil |<-- | b | o |<-- | c | o | | ||
| 1171 | | | | | | | | | | | | | | | ||
| 1172 | ------------- | --------- | - | -------- | - | ||
| 1173 | | | | | | ||
| 1174 | ------------- ------------ | ||
| 1175 | @end group | ||
| 1176 | @end smallexample | ||
| 1177 | @end defun | ||
| 1178 | |||
| 1179 | @defun sort list predicate | 1127 | @defun sort list predicate |
| 1180 | @cindex stable sort | 1128 | @cindex stable sort |
| 1181 | @cindex sorting lists | 1129 | @cindex sorting lists |
diff --git a/doc/lispref/sequences.texi b/doc/lispref/sequences.texi index c96f1222f3f..da53990b449 100644 --- a/doc/lispref/sequences.texi +++ b/doc/lispref/sequences.texi | |||
| @@ -260,6 +260,75 @@ x | |||
| 260 | @end example | 260 | @end example |
| 261 | @end defun | 261 | @end defun |
| 262 | 262 | ||
| 263 | @defun nreverse seq | ||
| 264 | @cindex reversing a list | ||
| 265 | @cindex reversing a vector | ||
| 266 | This function reverses the order of the elements of @var{seq}. | ||
| 267 | If @var{seq} is a list, @code{nreverse} alters its by reversing the @sc{cdr}s | ||
| 268 | in the cons cells. The cons cell that used to be the last one in @var{seq} | ||
| 269 | becomes the first cons cell of the value. If @var{seq} is a vector or | ||
| 270 | bool vector, its items are placed in the same vector in a reversed order. | ||
| 271 | |||
| 272 | For example: | ||
| 273 | |||
| 274 | @example | ||
| 275 | @group | ||
| 276 | (setq x '(a b c)) | ||
| 277 | @result{} (a b c) | ||
| 278 | @end group | ||
| 279 | @group | ||
| 280 | x | ||
| 281 | @result{} (a b c) | ||
| 282 | (nreverse x) | ||
| 283 | @result{} (c b a) | ||
| 284 | @end group | ||
| 285 | @group | ||
| 286 | ;; @r{The cons cell that was first is now last.} | ||
| 287 | x | ||
| 288 | @result{} (a) | ||
| 289 | @end group | ||
| 290 | @end example | ||
| 291 | |||
| 292 | To avoid confusion, we usually store the result of @code{nreverse} | ||
| 293 | back in the same variable which held the original list: | ||
| 294 | |||
| 295 | @example | ||
| 296 | (setq x (nreverse x)) | ||
| 297 | @end example | ||
| 298 | |||
| 299 | Here is the @code{nreverse} of our favorite example, @code{(a b c)}, | ||
| 300 | presented graphically: | ||
| 301 | |||
| 302 | @smallexample | ||
| 303 | @group | ||
| 304 | @r{Original list head:} @r{Reversed list:} | ||
| 305 | ------------- ------------- ------------ | ||
| 306 | | car | cdr | | car | cdr | | car | cdr | | ||
| 307 | | a | nil |<-- | b | o |<-- | c | o | | ||
| 308 | | | | | | | | | | | | | | | ||
| 309 | ------------- | --------- | - | -------- | - | ||
| 310 | | | | | | ||
| 311 | ------------- ------------ | ||
| 312 | @end group | ||
| 313 | @end smallexample | ||
| 314 | |||
| 315 | For the vector, it is even simpler because you don't need setq: | ||
| 316 | |||
| 317 | @example | ||
| 318 | (setq x [1 2 3 4]) | ||
| 319 | @result{} [1 2 3 4] | ||
| 320 | (nreverse x) | ||
| 321 | @result{} [4 3 2 1] | ||
| 322 | x | ||
| 323 | @result{} [4 3 2 1] | ||
| 324 | @end example | ||
| 325 | |||
| 326 | Note that unlike @code{reverse}, this function doesn't work with strings. | ||
| 327 | Although you can alter string data by using @code{aset}, it is strongly | ||
| 328 | encouraged to treat strings as immutable. | ||
| 329 | |||
| 330 | @end defun | ||
| 331 | |||
| 263 | @node Arrays | 332 | @node Arrays |
| 264 | @section Arrays | 333 | @section Arrays |
| 265 | @cindex array | 334 | @cindex array |
diff --git a/src/ChangeLog b/src/ChangeLog index ce51b26cf43..f82a6a298ae 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | 2014-05-15 Dmitry Antipov <dmantipov@yandex.ru> | 1 | 2014-05-15 Dmitry Antipov <dmantipov@yandex.ru> |
| 2 | 2 | ||
| 3 | * fns.c (Freverse): Allow vectors, bool vectors and strings. | 3 | * fns.c (Freverse): Allow vectors, bool vectors and strings. |
| 4 | (Fnreverse): Allow vectors and bool vectors. | ||
| 4 | 5 | ||
| 5 | 2014-05-14 Dmitry Antipov <dmantipov@yandex.ru> | 6 | 2014-05-14 Dmitry Antipov <dmantipov@yandex.ru> |
| 6 | 7 | ||
| @@ -1697,25 +1697,55 @@ changing the value of a sequence `foo'. */) | |||
| 1697 | } | 1697 | } |
| 1698 | 1698 | ||
| 1699 | DEFUN ("nreverse", Fnreverse, Snreverse, 1, 1, 0, | 1699 | DEFUN ("nreverse", Fnreverse, Snreverse, 1, 1, 0, |
| 1700 | doc: /* Reverse LIST by modifying cdr pointers. | 1700 | doc: /* Reverse order of items in a list or vector SEQ. |
| 1701 | Return the reversed list. Expects a properly nil-terminated list. */) | 1701 | If SEQ is a list, it should be nil-terminated, and reversed |
| 1702 | (Lisp_Object list) | 1702 | by modifying cdr pointers. Return the reversed SEQ. |
| 1703 | |||
| 1704 | Note that unlike `reverse', this function doesn't work with strings. | ||
| 1705 | It is strongly encouraged to treat them as immutable. */) | ||
| 1706 | (Lisp_Object seq) | ||
| 1703 | { | 1707 | { |
| 1704 | register Lisp_Object prev, tail, next; | 1708 | if (NILP (seq)) |
| 1709 | return seq; | ||
| 1710 | else if (CONSP (seq)) | ||
| 1711 | { | ||
| 1712 | Lisp_Object prev, tail, next; | ||
| 1705 | 1713 | ||
| 1706 | if (NILP (list)) return list; | 1714 | for (prev = Qnil, tail = seq; !NILP (tail); tail = next) |
| 1707 | prev = Qnil; | 1715 | { |
| 1708 | tail = list; | 1716 | QUIT; |
| 1709 | while (!NILP (tail)) | 1717 | CHECK_LIST_CONS (tail, tail); |
| 1718 | next = XCDR (tail); | ||
| 1719 | Fsetcdr (tail, prev); | ||
| 1720 | prev = tail; | ||
| 1721 | } | ||
| 1722 | seq = prev; | ||
| 1723 | } | ||
| 1724 | else if (VECTORP (seq)) | ||
| 1710 | { | 1725 | { |
| 1711 | QUIT; | 1726 | ptrdiff_t i, size = ASIZE (seq); |
| 1712 | CHECK_LIST_CONS (tail, tail); | 1727 | |
| 1713 | next = XCDR (tail); | 1728 | for (i = 0; i < size / 2; i++) |
| 1714 | Fsetcdr (tail, prev); | 1729 | { |
| 1715 | prev = tail; | 1730 | Lisp_Object tem = AREF (seq, i); |
| 1716 | tail = next; | 1731 | ASET (seq, i, AREF (seq, size - i - 1)); |
| 1732 | ASET (seq, size - i - 1, tem); | ||
| 1733 | } | ||
| 1717 | } | 1734 | } |
| 1718 | return prev; | 1735 | else if (BOOL_VECTOR_P (seq)) |
| 1736 | { | ||
| 1737 | ptrdiff_t i, size = bool_vector_size (seq); | ||
| 1738 | |||
| 1739 | for (i = 0; i < size / 2; i++) | ||
| 1740 | { | ||
| 1741 | bool tem = bool_vector_bitref (seq, i); | ||
| 1742 | bool_vector_set (seq, i, bool_vector_bitref (seq, size - i - 1)); | ||
| 1743 | bool_vector_set (seq, size - i - 1, tem); | ||
| 1744 | } | ||
| 1745 | } | ||
| 1746 | else | ||
| 1747 | wrong_type_argument (Qarrayp, seq); | ||
| 1748 | return seq; | ||
| 1719 | } | 1749 | } |
| 1720 | 1750 | ||
| 1721 | DEFUN ("reverse", Freverse, Sreverse, 1, 1, 0, | 1751 | DEFUN ("reverse", Freverse, Sreverse, 1, 1, 0, |
diff --git a/test/ChangeLog b/test/ChangeLog index cd5398e9b99..3fed9759ca7 100644 --- a/test/ChangeLog +++ b/test/ChangeLog | |||
| @@ -1,6 +1,8 @@ | |||
| 1 | 2014-05-15 Dmitry Antipov <dmantipov@yandex.ru> | 1 | 2014-05-15 Dmitry Antipov <dmantipov@yandex.ru> |
| 2 | 2 | ||
| 3 | * automated/fns-tests.el: New file. | 3 | * automated/fns-tests.el: New file. |
| 4 | * automated/fns-tests.el (fns-tests-nreverse) | ||
| 5 | (fns-tests-nreverse-bool-vector): New tests. | ||
| 4 | 6 | ||
| 5 | 2014-05-08 Glenn Morris <rgm@gnu.org> | 7 | 2014-05-08 Glenn Morris <rgm@gnu.org> |
| 6 | 8 | ||
diff --git a/test/automated/fns-tests.el b/test/automated/fns-tests.el index 2e71854261e..577298cddf4 100644 --- a/test/automated/fns-tests.el +++ b/test/automated/fns-tests.el | |||
| @@ -28,12 +28,44 @@ | |||
| 28 | (should-error (reverse)) | 28 | (should-error (reverse)) |
| 29 | (should-error (reverse 1)) | 29 | (should-error (reverse 1)) |
| 30 | (should-error (reverse (make-char-table 'foo))) | 30 | (should-error (reverse (make-char-table 'foo))) |
| 31 | (should (equal [] (reverse []))) | ||
| 32 | (should (equal [0] (reverse [0]))) | ||
| 31 | (should (equal [1 2 3 4] (reverse (reverse [1 2 3 4])))) | 33 | (should (equal [1 2 3 4] (reverse (reverse [1 2 3 4])))) |
| 34 | (should (equal '(a b c d) (reverse (reverse '(a b c d))))) | ||
| 32 | (should (equal "xyzzy" (reverse (reverse "xyzzy")))) | 35 | (should (equal "xyzzy" (reverse (reverse "xyzzy")))) |
| 33 | (should (equal "こんにちは / コンニチハ" (reverse (reverse "こんにちは / コンニチハ"))))) | 36 | (should (equal "こんにちは / コンニチハ" (reverse (reverse "こんにちは / コンニチハ"))))) |
| 34 | 37 | ||
| 38 | (ert-deftest fns-tests-nreverse () | ||
| 39 | (should-error (nreverse)) | ||
| 40 | (should-error (nreverse 1)) | ||
| 41 | (should-error (nreverse (make-char-table 'foo))) | ||
| 42 | (should-error (nreverse "xyzzy")) | ||
| 43 | (let ((A [])) | ||
| 44 | (nreverse A) | ||
| 45 | (should (equal A []))) | ||
| 46 | (let ((A [0])) | ||
| 47 | (nreverse A) | ||
| 48 | (should (equal A [0]))) | ||
| 49 | (let ((A [1 2 3 4])) | ||
| 50 | (nreverse A) | ||
| 51 | (should (equal A [4 3 2 1]))) | ||
| 52 | (let ((A [1 2 3 4])) | ||
| 53 | (nreverse A) | ||
| 54 | (nreverse A) | ||
| 55 | (should (equal A [1 2 3 4]))) | ||
| 56 | (let* ((A [1 2 3 4]) | ||
| 57 | (B (nreverse (nreverse A)))) | ||
| 58 | (should (equal A B)))) | ||
| 59 | |||
| 35 | (ert-deftest fns-tests-reverse-bool-vector () | 60 | (ert-deftest fns-tests-reverse-bool-vector () |
| 36 | (let ((A (make-bool-vector 10 nil))) | 61 | (let ((A (make-bool-vector 10 nil))) |
| 37 | (dotimes (i 5) (aset A i t)) | 62 | (dotimes (i 5) (aset A i t)) |
| 38 | (should (equal [nil nil nil nil nil t t t t t] (vconcat (reverse A)))) | 63 | (should (equal [nil nil nil nil nil t t t t t] (vconcat (reverse A)))) |
| 39 | (should (equal A (reverse (reverse A)))))) | 64 | (should (equal A (reverse (reverse A)))))) |
| 65 | |||
| 66 | (ert-deftest fns-tests-nreverse-bool-vector () | ||
| 67 | (let ((A (make-bool-vector 10 nil))) | ||
| 68 | (dotimes (i 5) (aset A i t)) | ||
| 69 | (nreverse A) | ||
| 70 | (should (equal [nil nil nil nil nil t t t t t] (vconcat A))) | ||
| 71 | (should (equal [t t t t t nil nil nil nil nil] (vconcat (nreverse A)))))) | ||