diff options
| author | Mattias EngdegÄrd | 2025-10-10 15:39:15 +0200 |
|---|---|---|
| committer | Mattias EngdegÄrd | 2025-10-20 11:39:16 +0200 |
| commit | d1b3eb7eec64ffb9f2d89efda21660cab92bcf0c (patch) | |
| tree | f72ab3aa242a7c81d4e0bc449549f0ae92af231a | |
| parent | cfe3c1c840d279d584350d2426b572e211df7c93 (diff) | |
| download | emacs-d1b3eb7eec64ffb9f2d89efda21660cab92bcf0c.tar.gz emacs-d1b3eb7eec64ffb9f2d89efda21660cab92bcf0c.zip | |
Add any and all (bug#79611)
* lisp/subr.el (all, any): New.
* test/lisp/subr-tests.el (subr-all, subr-any): New tests.
* doc/lispref/lists.texi (List Elements): Document.
* etc/NEWS: Announce.
| -rw-r--r-- | doc/lispref/lists.texi | 27 | ||||
| -rw-r--r-- | etc/NEWS | 5 | ||||
| -rw-r--r-- | lisp/subr.el | 14 | ||||
| -rw-r--r-- | test/lisp/subr-tests.el | 29 |
4 files changed, 75 insertions, 0 deletions
diff --git a/doc/lispref/lists.texi b/doc/lispref/lists.texi index da6d167c740..37ef8d46525 100644 --- a/doc/lispref/lists.texi +++ b/doc/lispref/lists.texi | |||
| @@ -415,6 +415,33 @@ will return a list equal to @var{list}. | |||
| 415 | @end example | 415 | @end example |
| 416 | @end defun | 416 | @end defun |
| 417 | 417 | ||
| 418 | @defun all pred list | ||
| 419 | This function returns @code{t} if @var{pred} is true for all elements in | ||
| 420 | @var{list}. | ||
| 421 | |||
| 422 | @example | ||
| 423 | @group | ||
| 424 | (all #'numberp '(1 2 3 4)) @result{} t | ||
| 425 | (all #'numberp '(1 2 a b 3 4)) @result{} nil | ||
| 426 | (all #'numberp '()) @result{} t | ||
| 427 | @end group | ||
| 428 | @end example | ||
| 429 | @end defun | ||
| 430 | |||
| 431 | @defun any pred list | ||
| 432 | This function returns non-@code{nil} if @var{pred} is true for at least | ||
| 433 | one element in @var{list}. The returned value is the longest @var{list} | ||
| 434 | suffix whose first element satisfies @var{pred}. | ||
| 435 | |||
| 436 | @example | ||
| 437 | @group | ||
| 438 | (any #'symbolp '(1 2 3 4)) @result{} nil | ||
| 439 | (any #'symbolp '(1 2 a b 3 4)) @result{} (a b 3 4) | ||
| 440 | (any #'symbolp '()) @result{} nil | ||
| 441 | @end group | ||
| 442 | @end example | ||
| 443 | @end defun | ||
| 444 | |||
| 418 | @defun last list &optional n | 445 | @defun last list &optional n |
| 419 | This function returns the last link of @var{list}. The @code{car} of | 446 | This function returns the last link of @var{list}. The @code{car} of |
| 420 | this link is the list's last element. If @var{list} is null, | 447 | this link is the list's last element. If @var{list} is null, |
| @@ -3143,6 +3143,11 @@ signal an error if they are given a non-integer. | |||
| 3143 | These work like 'drop' and 'take' but use a predicate instead of counting. | 3143 | These work like 'drop' and 'take' but use a predicate instead of counting. |
| 3144 | 3144 | ||
| 3145 | +++ | 3145 | +++ |
| 3146 | ** New functions 'any' and 'all'. | ||
| 3147 | These return non-nil for lists where any and all elements, respectively, | ||
| 3148 | satisfy a given predicate. | ||
| 3149 | |||
| 3150 | +++ | ||
| 3146 | ** The 'defvar-local' macro second argument is now optional. | 3151 | ** The 'defvar-local' macro second argument is now optional. |
| 3147 | This means that you can now call it with just one argument, like | 3152 | This means that you can now call it with just one argument, like |
| 3148 | 'defvar', to declare a variable both special, and buffer-local. | 3153 | 'defvar', to declare a variable both special, and buffer-local. |
diff --git a/lisp/subr.el b/lisp/subr.el index 403e9dac376..216ad5eb4ab 100644 --- a/lisp/subr.el +++ b/lisp/subr.el | |||
| @@ -1176,6 +1176,20 @@ side-effects, and the argument LIST is not modified." | |||
| 1176 | (while (and list (funcall pred (car list))) | 1176 | (while (and list (funcall pred (car list))) |
| 1177 | (setq list (cdr list))) | 1177 | (setq list (cdr list))) |
| 1178 | list) | 1178 | list) |
| 1179 | |||
| 1180 | (defun all (pred list) | ||
| 1181 | "Non-nil if PRED is true for all elements in LIST." | ||
| 1182 | (declare (compiler-macro (lambda (_) `(not (drop-while ,pred ,list))))) | ||
| 1183 | (not (drop-while pred list))) | ||
| 1184 | |||
| 1185 | (defun any (pred list) | ||
| 1186 | "Non-nil if PRED is true for at least one element in LIST. | ||
| 1187 | Returns the LIST suffix starting at the first element that satisfies PRED, | ||
| 1188 | or nil if none does." | ||
| 1189 | (declare (compiler-macro | ||
| 1190 | (lambda (_) | ||
| 1191 | `(drop-while (lambda (x) (not (funcall ,pred x))) ,list)))) | ||
| 1192 | (drop-while (lambda (x) (not (funcall pred x))) list)) | ||
| 1179 | 1193 | ||
| 1180 | ;;;; Keymap support. | 1194 | ;;;; Keymap support. |
| 1181 | 1195 | ||
diff --git a/test/lisp/subr-tests.el b/test/lisp/subr-tests.el index ae5932d96b3..fc980eae596 100644 --- a/test/lisp/subr-tests.el +++ b/test/lisp/subr-tests.el | |||
| @@ -1545,5 +1545,34 @@ final or penultimate step during initialization.")) | |||
| 1545 | (should (equal (funcall (subr--identity #'take-while) #'plusp ls) | 1545 | (should (equal (funcall (subr--identity #'take-while) #'plusp ls) |
| 1546 | '(3 2 1))))) | 1546 | '(3 2 1))))) |
| 1547 | 1547 | ||
| 1548 | (ert-deftest subr-all () | ||
| 1549 | (should (equal (all #'hash-table-p nil) t)) | ||
| 1550 | (let ((ls (append '(3 2 1) '(0) '(-1 -2 -3)))) | ||
| 1551 | (should (equal (all #'numberp ls) t)) | ||
| 1552 | (should (equal (all (lambda (x) (numberp x)) ls) t)) | ||
| 1553 | (should (equal (all #'plusp ls) nil)) | ||
| 1554 | (should (equal (all #'bufferp ls) nil)) | ||
| 1555 | (let ((z 9)) | ||
| 1556 | (should (equal (all (lambda (x) (< x z)) ls) t)) | ||
| 1557 | (should (equal (all (lambda (x) (> x (- z 9))) ls) nil)) | ||
| 1558 | (should (equal (all (lambda (x) (> x z)) ls) nil))) | ||
| 1559 | (should (equal (funcall (subr--identity #'all) #'plusp ls) nil)) | ||
| 1560 | (should (equal (funcall (subr--identity #'all) #'numberp ls) t)))) | ||
| 1561 | |||
| 1562 | (ert-deftest subr-any () | ||
| 1563 | (should (equal (any #'hash-table-p nil) nil)) | ||
| 1564 | (let ((ls (append '(3 2 1) '(0) '(-1 -2 -3)))) | ||
| 1565 | (should (equal (any #'numberp ls) ls)) | ||
| 1566 | (should (equal (any (lambda (x) (numberp x)) ls) ls)) | ||
| 1567 | (should (equal (any #'plusp ls) ls)) | ||
| 1568 | (should (equal (any #'zerop ls) '(0 -1 -2 -3))) | ||
| 1569 | (should (equal (any #'bufferp ls) nil)) | ||
| 1570 | (let ((z 9)) | ||
| 1571 | (should (equal (any (lambda (x) (< x z)) ls) ls)) | ||
| 1572 | (should (equal (any (lambda (x) (< x (- z 9))) ls) '(-1 -2 -3))) | ||
| 1573 | (should (equal (any (lambda (x) (> x z)) ls) nil))) | ||
| 1574 | (should (equal (funcall (subr--identity #'any) #'minusp ls) '(-1 -2 -3))) | ||
| 1575 | (should (equal (funcall (subr--identity #'any) #'stringp ls) nil)))) | ||
| 1576 | |||
| 1548 | (provide 'subr-tests) | 1577 | (provide 'subr-tests) |
| 1549 | ;;; subr-tests.el ends here | 1578 | ;;; subr-tests.el ends here |