* 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.
This commit is contained in:
parent
92491099f7
commit
ddc30c996a
7 changed files with 151 additions and 69 deletions
|
@ -1,7 +1,7 @@
|
|||
2014-05-15 Dmitry Antipov <dmantipov@yandex.ru>
|
||||
|
||||
* lists.texi (Building Cons Cells and Lists): Remove
|
||||
description of `reverse' and generalize it...
|
||||
description of `reverse' and `'nreverse' to generalize them...
|
||||
* sequences.texi (Sequences): ...for sequences here.
|
||||
|
||||
2014-05-14 Glenn Morris <rgm@gnu.org>
|
||||
|
|
|
@ -1124,58 +1124,6 @@ each time you run it! Here is what happens:
|
|||
@end smallexample
|
||||
@end defun
|
||||
|
||||
@defun nreverse list
|
||||
@cindex reversing a list
|
||||
This function reverses the order of the elements of @var{list}.
|
||||
Unlike @code{reverse}, @code{nreverse} alters its argument by reversing
|
||||
the @sc{cdr}s in the cons cells forming the list. The cons cell that
|
||||
used to be the last one in @var{list} becomes the first cons cell of the
|
||||
value.
|
||||
|
||||
For example:
|
||||
|
||||
@example
|
||||
@group
|
||||
(setq x '(a b c))
|
||||
@result{} (a b c)
|
||||
@end group
|
||||
@group
|
||||
x
|
||||
@result{} (a b c)
|
||||
(nreverse x)
|
||||
@result{} (c b a)
|
||||
@end group
|
||||
@group
|
||||
;; @r{The cons cell that was first is now last.}
|
||||
x
|
||||
@result{} (a)
|
||||
@end group
|
||||
@end example
|
||||
|
||||
To avoid confusion, we usually store the result of @code{nreverse}
|
||||
back in the same variable which held the original list:
|
||||
|
||||
@example
|
||||
(setq x (nreverse x))
|
||||
@end example
|
||||
|
||||
Here is the @code{nreverse} of our favorite example, @code{(a b c)},
|
||||
presented graphically:
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
@r{Original list head:} @r{Reversed list:}
|
||||
------------- ------------- ------------
|
||||
| car | cdr | | car | cdr | | car | cdr |
|
||||
| a | nil |<-- | b | o |<-- | c | o |
|
||||
| | | | | | | | | | | | |
|
||||
------------- | --------- | - | -------- | -
|
||||
| | | |
|
||||
------------- ------------
|
||||
@end group
|
||||
@end smallexample
|
||||
@end defun
|
||||
|
||||
@defun sort list predicate
|
||||
@cindex stable sort
|
||||
@cindex sorting lists
|
||||
|
|
|
@ -260,6 +260,75 @@ x
|
|||
@end example
|
||||
@end defun
|
||||
|
||||
@defun nreverse seq
|
||||
@cindex reversing a list
|
||||
@cindex reversing a vector
|
||||
This function reverses the order of the elements of @var{seq}.
|
||||
If @var{seq} is a list, @code{nreverse} alters its by reversing the @sc{cdr}s
|
||||
in the cons cells. The cons cell that used to be the last one in @var{seq}
|
||||
becomes the first cons cell of the value. If @var{seq} is a vector or
|
||||
bool vector, its items are placed in the same vector in a reversed order.
|
||||
|
||||
For example:
|
||||
|
||||
@example
|
||||
@group
|
||||
(setq x '(a b c))
|
||||
@result{} (a b c)
|
||||
@end group
|
||||
@group
|
||||
x
|
||||
@result{} (a b c)
|
||||
(nreverse x)
|
||||
@result{} (c b a)
|
||||
@end group
|
||||
@group
|
||||
;; @r{The cons cell that was first is now last.}
|
||||
x
|
||||
@result{} (a)
|
||||
@end group
|
||||
@end example
|
||||
|
||||
To avoid confusion, we usually store the result of @code{nreverse}
|
||||
back in the same variable which held the original list:
|
||||
|
||||
@example
|
||||
(setq x (nreverse x))
|
||||
@end example
|
||||
|
||||
Here is the @code{nreverse} of our favorite example, @code{(a b c)},
|
||||
presented graphically:
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
@r{Original list head:} @r{Reversed list:}
|
||||
------------- ------------- ------------
|
||||
| car | cdr | | car | cdr | | car | cdr |
|
||||
| a | nil |<-- | b | o |<-- | c | o |
|
||||
| | | | | | | | | | | | |
|
||||
------------- | --------- | - | -------- | -
|
||||
| | | |
|
||||
------------- ------------
|
||||
@end group
|
||||
@end smallexample
|
||||
|
||||
For the vector, it is even simpler because you don't need setq:
|
||||
|
||||
@example
|
||||
(setq x [1 2 3 4])
|
||||
@result{} [1 2 3 4]
|
||||
(nreverse x)
|
||||
@result{} [4 3 2 1]
|
||||
x
|
||||
@result{} [4 3 2 1]
|
||||
@end example
|
||||
|
||||
Note that unlike @code{reverse}, this function doesn't work with strings.
|
||||
Although you can alter string data by using @code{aset}, it is strongly
|
||||
encouraged to treat strings as immutable.
|
||||
|
||||
@end defun
|
||||
|
||||
@node Arrays
|
||||
@section Arrays
|
||||
@cindex array
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
2014-05-15 Dmitry Antipov <dmantipov@yandex.ru>
|
||||
|
||||
* fns.c (Freverse): Allow vectors, bool vectors and strings.
|
||||
(Fnreverse): Allow vectors and bool vectors.
|
||||
|
||||
2014-05-14 Dmitry Antipov <dmantipov@yandex.ru>
|
||||
|
||||
|
|
62
src/fns.c
62
src/fns.c
|
@ -1697,25 +1697,55 @@ changing the value of a sequence `foo'. */)
|
|||
}
|
||||
|
||||
DEFUN ("nreverse", Fnreverse, Snreverse, 1, 1, 0,
|
||||
doc: /* Reverse LIST by modifying cdr pointers.
|
||||
Return the reversed list. Expects a properly nil-terminated list. */)
|
||||
(Lisp_Object list)
|
||||
{
|
||||
register Lisp_Object prev, tail, next;
|
||||
doc: /* Reverse order of items in a list or vector SEQ.
|
||||
If SEQ is a list, it should be nil-terminated, and reversed
|
||||
by modifying cdr pointers. Return the reversed SEQ.
|
||||
|
||||
if (NILP (list)) return list;
|
||||
prev = Qnil;
|
||||
tail = list;
|
||||
while (!NILP (tail))
|
||||
Note that unlike `reverse', this function doesn't work with strings.
|
||||
It is strongly encouraged to treat them as immutable. */)
|
||||
(Lisp_Object seq)
|
||||
{
|
||||
if (NILP (seq))
|
||||
return seq;
|
||||
else if (CONSP (seq))
|
||||
{
|
||||
QUIT;
|
||||
CHECK_LIST_CONS (tail, tail);
|
||||
next = XCDR (tail);
|
||||
Fsetcdr (tail, prev);
|
||||
prev = tail;
|
||||
tail = next;
|
||||
Lisp_Object prev, tail, next;
|
||||
|
||||
for (prev = Qnil, tail = seq; !NILP (tail); tail = next)
|
||||
{
|
||||
QUIT;
|
||||
CHECK_LIST_CONS (tail, tail);
|
||||
next = XCDR (tail);
|
||||
Fsetcdr (tail, prev);
|
||||
prev = tail;
|
||||
}
|
||||
seq = prev;
|
||||
}
|
||||
return prev;
|
||||
else if (VECTORP (seq))
|
||||
{
|
||||
ptrdiff_t i, size = ASIZE (seq);
|
||||
|
||||
for (i = 0; i < size / 2; i++)
|
||||
{
|
||||
Lisp_Object tem = AREF (seq, i);
|
||||
ASET (seq, i, AREF (seq, size - i - 1));
|
||||
ASET (seq, size - i - 1, tem);
|
||||
}
|
||||
}
|
||||
else if (BOOL_VECTOR_P (seq))
|
||||
{
|
||||
ptrdiff_t i, size = bool_vector_size (seq);
|
||||
|
||||
for (i = 0; i < size / 2; i++)
|
||||
{
|
||||
bool tem = bool_vector_bitref (seq, i);
|
||||
bool_vector_set (seq, i, bool_vector_bitref (seq, size - i - 1));
|
||||
bool_vector_set (seq, size - i - 1, tem);
|
||||
}
|
||||
}
|
||||
else
|
||||
wrong_type_argument (Qarrayp, seq);
|
||||
return seq;
|
||||
}
|
||||
|
||||
DEFUN ("reverse", Freverse, Sreverse, 1, 1, 0,
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
2014-05-15 Dmitry Antipov <dmantipov@yandex.ru>
|
||||
|
||||
* automated/fns-tests.el: New file.
|
||||
* automated/fns-tests.el (fns-tests-nreverse)
|
||||
(fns-tests-nreverse-bool-vector): New tests.
|
||||
|
||||
2014-05-08 Glenn Morris <rgm@gnu.org>
|
||||
|
||||
|
|
|
@ -28,12 +28,44 @@
|
|||
(should-error (reverse))
|
||||
(should-error (reverse 1))
|
||||
(should-error (reverse (make-char-table 'foo)))
|
||||
(should (equal [] (reverse [])))
|
||||
(should (equal [0] (reverse [0])))
|
||||
(should (equal [1 2 3 4] (reverse (reverse [1 2 3 4]))))
|
||||
(should (equal '(a b c d) (reverse (reverse '(a b c d)))))
|
||||
(should (equal "xyzzy" (reverse (reverse "xyzzy"))))
|
||||
(should (equal "こんにちは / コンニチハ" (reverse (reverse "こんにちは / コンニチハ")))))
|
||||
|
||||
(ert-deftest fns-tests-nreverse ()
|
||||
(should-error (nreverse))
|
||||
(should-error (nreverse 1))
|
||||
(should-error (nreverse (make-char-table 'foo)))
|
||||
(should-error (nreverse "xyzzy"))
|
||||
(let ((A []))
|
||||
(nreverse A)
|
||||
(should (equal A [])))
|
||||
(let ((A [0]))
|
||||
(nreverse A)
|
||||
(should (equal A [0])))
|
||||
(let ((A [1 2 3 4]))
|
||||
(nreverse A)
|
||||
(should (equal A [4 3 2 1])))
|
||||
(let ((A [1 2 3 4]))
|
||||
(nreverse A)
|
||||
(nreverse A)
|
||||
(should (equal A [1 2 3 4])))
|
||||
(let* ((A [1 2 3 4])
|
||||
(B (nreverse (nreverse A))))
|
||||
(should (equal A B))))
|
||||
|
||||
(ert-deftest fns-tests-reverse-bool-vector ()
|
||||
(let ((A (make-bool-vector 10 nil)))
|
||||
(dotimes (i 5) (aset A i t))
|
||||
(should (equal [nil nil nil nil nil t t t t t] (vconcat (reverse A))))
|
||||
(should (equal A (reverse (reverse A))))))
|
||||
|
||||
(ert-deftest fns-tests-nreverse-bool-vector ()
|
||||
(let ((A (make-bool-vector 10 nil)))
|
||||
(dotimes (i 5) (aset A i t))
|
||||
(nreverse A)
|
||||
(should (equal [nil nil nil nil nil t t t t t] (vconcat A)))
|
||||
(should (equal [t t t t t nil nil nil nil nil] (vconcat (nreverse A))))))
|
||||
|
|
Loading…
Add table
Reference in a new issue