Skip to content

Commit a56c3ec

Browse files
committed
compat-31: New functions take-while, drop-while, all, any
1 parent dd81758 commit a56c3ec

File tree

4 files changed

+137
-0
lines changed

4 files changed

+137
-0
lines changed

NEWS.org

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
- compat-31: New extended function =seconds-to-string=.
1818
- compat-31: New function =hash-table-contains-p=.
1919
- compat-31: New function =remove-display-text-property=.
20+
- compat-31: New functions =drop-while=, =take-while=, =any=, =all=.
2021
- Drop support for Emacs 24.x. Emacs 25.1 is required now. In case
2122
Emacs 24.x support is still needed, Compat 30 can be used.
2223

compat-31.el

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,30 @@
2929

3030
;;;; Defined in subr.el
3131

32+
(compat-defun take-while (pred list) ;; <compat-tests:take-while>
33+
"Return the longest prefix of LIST whose elements satisfy PRED."
34+
(let ((r nil))
35+
(while (and list (funcall pred (car list)))
36+
(push (car list) r)
37+
(setq list (cdr list)))
38+
(nreverse r)))
39+
40+
(compat-defun drop-while (pred list) ;; <compat-tests:drop-while>
41+
"Skip initial elements of LIST satisfying PRED and return the rest."
42+
(while (and list (funcall pred (car list)))
43+
(setq list (cdr list)))
44+
list)
45+
46+
(compat-defun all (pred list) ;; <compat-tests:all>
47+
"Non-nil if PRED is true for all elements in LIST."
48+
(not (drop-while pred list)))
49+
50+
(compat-defun any (pred list) ;; <compat-tests:any>
51+
"Non-nil if PRED is true for at least one element in LIST.
52+
Returns the LIST suffix starting at the first element that satisfies PRED,
53+
or nil if none does."
54+
(drop-while (lambda (x) (not (funcall pred x))) list))
55+
3256
(compat-defun hash-table-contains-p (key table) ;; <compat-tests:hash-table-contains-p>
3357
"Return non-nil if TABLE has an element with KEY."
3458
(declare (side-effect-free t))

compat-tests.el

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3033,6 +3033,59 @@
30333033
(with-temp-buffer
30343034
(should-equal (take 3 (widget-create 'key)) '(key :value ""))))
30353035

3036+
(ert-deftest compat-drop-while ()
3037+
(should (equal (drop-while #'hash-table-p nil) nil))
3038+
(let ((ls (append '(3 2 1) '(0) '(-1 -2 -3))))
3039+
(should (equal (drop-while #'plusp ls) '(0 -1 -2 -3)))
3040+
(should (equal (drop-while (lambda (x) (plusp x)) ls) '(0 -1 -2 -3)))
3041+
(let ((z 1))
3042+
(should (equal (drop-while (lambda (x) (> x z)) ls) '(1 0 -1 -2 -3))))
3043+
(should (equal (drop-while #'bufferp ls) ls))
3044+
(should (equal (drop-while #'numberp ls) nil))
3045+
(should (equal (funcall (identity #'drop-while) #'plusp ls)
3046+
'(0 -1 -2 -3)))))
3047+
3048+
(ert-deftest compat-take-while ()
3049+
(should (equal (take-while #'hash-table-p nil) nil))
3050+
(let ((ls (append '(3 2 1) '(0) '(-1 -2 -3))))
3051+
(should (equal (take-while #'plusp ls) '(3 2 1)))
3052+
(should (equal (take-while (lambda (x) (plusp x)) ls) '(3 2 1)))
3053+
(let ((z 1))
3054+
(should (equal (take-while (lambda (x) (> x z)) ls) '(3 2))))
3055+
(should (equal (take-while #'bufferp ls) nil))
3056+
(should (equal (take-while #'numberp ls) ls))
3057+
(should (equal (funcall (identity #'take-while) #'plusp ls)
3058+
'(3 2 1)))))
3059+
3060+
(ert-deftest compat-all ()
3061+
(should (equal (all #'hash-table-p nil) t))
3062+
(let ((ls (append '(3 2 1) '(0) '(-1 -2 -3))))
3063+
(should (equal (all #'numberp ls) t))
3064+
(should (equal (all (lambda (x) (numberp x)) ls) t))
3065+
(should (equal (all #'plusp ls) nil))
3066+
(should (equal (all #'bufferp ls) nil))
3067+
(let ((z 9))
3068+
(should (equal (all (lambda (x) (< x z)) ls) t))
3069+
(should (equal (all (lambda (x) (> x (- z 9))) ls) nil))
3070+
(should (equal (all (lambda (x) (> x z)) ls) nil)))
3071+
(should (equal (funcall (identity #'all) #'plusp ls) nil))
3072+
(should (equal (funcall (identity #'all) #'numberp ls) t))))
3073+
3074+
(ert-deftest compat-any ()
3075+
(should (equal (any #'hash-table-p nil) nil))
3076+
(let ((ls (append '(3 2 1) '(0) '(-1 -2 -3))))
3077+
(should (equal (any #'numberp ls) ls))
3078+
(should (equal (any (lambda (x) (numberp x)) ls) ls))
3079+
(should (equal (any #'plusp ls) ls))
3080+
(should (equal (any #'zerop ls) '(0 -1 -2 -3)))
3081+
(should (equal (any #'bufferp ls) nil))
3082+
(let ((z 9))
3083+
(should (equal (any (lambda (x) (< x z)) ls) ls))
3084+
(should (equal (any (lambda (x) (< x (- z 9))) ls) '(-1 -2 -3)))
3085+
(should (equal (any (lambda (x) (> x z)) ls) nil)))
3086+
(should (equal (funcall (identity #'any) #'minusp ls) '(-1 -2 -3)))
3087+
(should (equal (funcall (identity #'any) #'stringp ls) nil))))
3088+
30363089
(ert-deftest compat-hash-table-contains-p ()
30373090
(let ((h (make-hash-table :test #'equal)))
30383091
(puthash :foo t h)

compat.texi

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3452,6 +3452,65 @@ older than 31.1. Note that due to upstream changes, it might happen
34523452
that there will be the need for changes, so use these functions with
34533453
care.
34543454

3455+
@c copied from lispref/lists.texi
3456+
@defun drop-while pred list
3457+
This function skips leading list elements for which the predicate @var{pred}
3458+
returns non-@code{nil}, and returns the rest.
3459+
3460+
@example
3461+
@group
3462+
(drop-while #'numberp '(1 2 a b 3 4))
3463+
@result{} (a b 3 4)
3464+
@end group
3465+
@end example
3466+
@end defun
3467+
3468+
@c copied from lispref/lists.texi
3469+
@defun take-while pred list
3470+
This function returns the leading list elements for which the predicate
3471+
@var{pred} returns non-@code{nil}, and ignores the rest.
3472+
3473+
In general,
3474+
@code{(append (take-while @var{p} @var{list}) (drop-while @var{p} @var{list}))}
3475+
will return a list equal to @var{list}.
3476+
3477+
@example
3478+
@group
3479+
(take-while #'numberp '(1 2 a b 3 4))
3480+
@result{} (1 2)
3481+
@end group
3482+
@end example
3483+
@end defun
3484+
3485+
@c copied from lispref/lists.texi
3486+
@defun all pred list
3487+
This function returns @code{t} if @var{pred} is true for all elements in
3488+
@var{list}.
3489+
3490+
@example
3491+
@group
3492+
(all #'numberp '(1 2 3 4)) @result{} t
3493+
(all #'numberp '(1 2 a b 3 4)) @result{} nil
3494+
(all #'numberp '()) @result{} t
3495+
@end group
3496+
@end example
3497+
@end defun
3498+
3499+
@c copied from lispref/lists.texi
3500+
@defun any pred list
3501+
This function returns non-@code{nil} if @var{pred} is true for at least
3502+
one element in @var{list}. The returned value is the longest @var{list}
3503+
suffix whose first element satisfies @var{pred}.
3504+
3505+
@example
3506+
@group
3507+
(any #'symbolp '(1 2 3 4)) @result{} nil
3508+
(any #'symbolp '(1 2 a b 3 4)) @result{} (a b 3 4)
3509+
(any #'symbolp '()) @result{} nil
3510+
@end group
3511+
@end example
3512+
@end defun
3513+
34553514
@c copied from lispref/display.texi
34563515
@defun remove-display-text-property start end spec &optional object
34573516
Remove the display specification @var{spec} from the text from

0 commit comments

Comments
 (0)