[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/dash 11a6296 1/2: Prefer n-ary over unary/binary combin
From: |
ELPA Syncer |
Subject: |
[elpa] externals/dash 11a6296 1/2: Prefer n-ary over unary/binary combinators |
Date: |
Thu, 8 Jul 2021 12:57:11 -0400 (EDT) |
branch: externals/dash
commit 11a629639111cb919ca6d2942270fb1999d540de
Author: Basil L. Contovounesios <contovob@tcd.ie>
Commit: Basil L. Contovounesios <contovob@tcd.ie>
Prefer n-ary over unary/binary combinators
This is a rewrite and extension of PR #72 to address issue #306.
For discussion, especially wrt performance, see PRs #72 and #308.
* dash.el (-on, -flip, -not, -orfn, -andfn): Return a variadic
function. Declare as pure and side-effect-free.
(-rotate-args): New combinator suggested by @vapniks in PR #72.
(-const): Declare as pure and side-effect-free.
* NEWS.md (2.19.0): Announce -rotate-args and variadic combinators.
* dev/examples.el (-partition-after-pred): Fix oddp bug waiting to
happen with negative dividends.
(-cons*): Check that &rest args are safe to mutate.
(-on, -flip, -const, -not, -orfn, -andfn): Extend tests.
(-rotate-args): New test.
* README.md:
* dash.texi: Regenerate docs.
---
NEWS.md | 4 ++
README.md | 113 ++++++++++++++++++++++++++--------------
dash.el | 126 ++++++++++++++++++++++++++++++++++----------
dash.texi | 138 +++++++++++++++++++++++++++++++++---------------
dev/examples.el | 159 ++++++++++++++++++++++++++++++++++++++++++++------------
5 files changed, 399 insertions(+), 141 deletions(-)
diff --git a/NEWS.md b/NEWS.md
index efcf675..bd9700e 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -18,6 +18,10 @@ See the end of the file for license conditions.
#### New features
+- The combinators `-on`, `-flip`, `-not`, `-andfn`, and `-orfn` now
+ return variadic functions that take any number of arguments (#308).
+- New combinator `-rotate-args` similar to `-flip`, but for arbitrary
+ arglist rotations (suggested by @vapniks, #72).
- New function `-every` and its anaphoric macro counterpart `--every`.
They are like the existing `-every-p` and `--every-p`, respectively,
but return the last non-`nil` result instead of just `t`.
diff --git a/README.md b/README.md
index c738bf9..00fc4d7 100644
--- a/README.md
+++ b/README.md
@@ -373,8 +373,9 @@ Functions that manipulate and compose other functions.
* [`-juxt`](#-juxt-rest-fns) `(&rest fns)`
* [`-compose`](#-compose-rest-fns) `(&rest fns)`
* [`-applify`](#-applify-fn) `(fn)`
-* [`-on`](#-on-operator-transformer) `(operator transformer)`
-* [`-flip`](#-flip-func) `(func)`
+* [`-on`](#-on-op-trans) `(op trans)`
+* [`-flip`](#-flip-fn) `(fn)`
+* [`-rotate-args`](#-rotate-args-n-fn) `(n fn)`
* [`-const`](#-const-c) `(c)`
* [`-cut`](#-cut-rest-params) `(&rest params)`
* [`-not`](#-not-pred) `(pred)`
@@ -1193,7 +1194,7 @@ Return the smallest value from `list` of numbers or
markers.
Take a comparison function `comparator` and a `list` and return
the least element of the list by the comparison function.
-See also combinator [`-on`](#-on-operator-transformer) which can transform the
values before
+See also combinator [`-on`](#-on-op-trans) which can transform the values
before
comparing them.
```el
@@ -1217,7 +1218,7 @@ Return the largest value from `list` of numbers or
markers.
Take a comparison function `comparator` and a `list` and return
the greatest element of the list by the comparison function.
-See also combinator [`-on`](#-on-operator-transformer) which can transform the
values before
+See also combinator [`-on`](#-on-op-trans) which can transform the values
before
comparing them.
```el
@@ -2892,30 +2893,56 @@ taking 1 argument which is a list of `n` arguments.
(funcall (-applify #'<) '(3 6)) ;; => t
```
-#### -on `(operator transformer)`
+#### -on `(op trans)`
-Return a function of two arguments that first applies
-`transformer` to each of them and then applies `operator` on the
-results (in the same order).
+Return a function that calls `trans` on each arg and `op` on the results.
+The returned function takes a variable number of arguments, calls
+the function `trans` on each one in turn, and then passes those
+results as the list of arguments to `op`, in the same order.
-In types: (b -> b -> c) -> (a -> b) -> a -> a -> c
+For example, the following pairs of expressions are morally
+equivalent:
+
+ (funcall (-on #'+ #'1+) 1 2 3) = (+ (1+ 1) (1+ 2) (1+ 3))
+ (funcall (-on #'+ #'1+)) = (+)
```el
-(-sort (-on '< 'length) '((1 2 3) (1) (1 2))) ;; => ((1) (1 2) (1 2 3))
-(-min-by (-on '> 'length) '((1 2 3) (4) (1 2))) ;; => (4)
-(-min-by (-on 'string-lessp 'number-to-string) '(2 100 22)) ;; => 22
+(-sort (-on #'< #'length) '((1 2 3) (1) (1 2))) ;; => ((1) (1 2) (1 2 3))
+(funcall (-on #'min #'string-to-number) "22" "2" "1" "12") ;; => 1
+(-min-by (-on #'> #'length) '((1 2 3) (4) (1 2))) ;; => (4)
```
-#### -flip `(func)`
+#### -flip `(fn)`
+
+Return a function that calls `fn` with its arguments reversed.
+The returned function takes the same number of arguments as `fn`.
+
+For example, the following two expressions are morally
+equivalent:
-Swap the order of arguments for binary function `func`.
+ (funcall (-flip #'-) 1 2) = (- 2 1)
-In types: (a -> b -> c) -> b -> a -> c
+See also: [`-rotate-args`](#-rotate-args-n-fn).
```el
-(funcall (-flip '<) 2 1) ;; => t
-(funcall (-flip '-) 3 8) ;; => 5
-(-sort (-flip '<) '(4 3 6 1)) ;; => (6 4 3 1)
+(-sort (-flip #'<) '(4 3 6 1)) ;; => (6 4 3 1)
+(funcall (-flip #'-) 3 2 1 10) ;; => 4
+(funcall (-flip #'1+) 1) ;; => 2
+```
+
+#### -rotate-args `(n fn)`
+
+Return a function that calls `fn` with args rotated `n` places to the right.
+The returned function takes the same number of arguments as `fn`,
+rotates the list of arguments `n` places to the right (left if `n` is
+negative) just like [`-rotate`](#-rotate-n-list), and applies `fn` to the
result.
+
+See also: [`-flip`](#-flip-fn).
+
+```el
+(funcall (-rotate-args -1 #'list) 1 2 3 4) ;; => (2 3 4 1)
+(funcall (-rotate-args 1 #'-) 1 10 100) ;; => 89
+(funcall (-rotate-args 2 #'list) 3 4 5 1 2) ;; => (1 2 3 4 5)
```
#### -const `(c)`
@@ -2926,8 +2953,8 @@ In types: a -> b -> a
```el
(funcall (-const 2) 1 3 "foo") ;; => 2
-(-map (-const 1) '("a" "b" "c" "d")) ;; => (1 1 1 1)
-(-sum (-map (-const 1) '("a" "b" "c" "d"))) ;; => 4
+(mapcar (-const 1) '("a" "b" "c" "d")) ;; => (1 1 1 1)
+(-sum (mapcar (-const 1) '("a" "b" "c" "d"))) ;; => 4
```
#### -cut `(&rest params)`
@@ -2945,40 +2972,50 @@ See `srfi-26` for detailed description.
#### -not `(pred)`
-Take a unary predicate `pred` and return a unary predicate
-that returns t if `pred` returns nil and nil if `pred` returns
-non-nil.
+Return a predicate that negates the result of `pred`.
+The returned predicate passes its arguments to `pred`. If `pred`
+returns nil, the result is non-nil; otherwise the result is nil.
+
+See also: [`-andfn`](#-andfn-rest-preds) and [`-orfn`](#-orfn-rest-preds).
```el
-(funcall (-not 'even?) 5) ;; => t
-(-filter (-not (-partial '< 4)) '(1 2 3 4 5 6 7 8)) ;; => (1 2 3 4)
+(funcall (-not #'numberp) "5") ;; => t
+(-sort (-not #'<) '(5 2 1 0 6)) ;; => (6 5 2 1 0)
+(-filter (-not (-partial #'< 4)) '(1 2 3 4 5 6 7 8)) ;; => (1 2 3 4)
```
#### -orfn `(&rest preds)`
-Take list of unary predicates `preds` and return a unary
-predicate with argument x that returns non-nil if at least one of
-the `preds` returns non-nil on x.
+Return a predicate that returns the first non-nil result of `preds`.
+The returned predicate takes a variable number of arguments,
+passes them to each predicate in `preds` in turn until one of them
+returns non-nil, and returns that non-nil result without calling
+the remaining `preds`. If all `preds` return nil, or if no `preds` are
+given, the returned predicate returns nil.
-In types: [a -> Bool] -> a -> Bool
+See also: [`-andfn`](#-andfn-rest-preds) and [`-not`](#-not-pred).
```el
-(-filter (-orfn 'even? (-partial (-flip '<) 5)) '(1 2 3 4 5 6 7 8 9 10)) ;; =>
(1 2 3 4 6 8 10)
-(funcall (-orfn 'stringp 'even?) "foo") ;; => t
+(-filter (-orfn #'natnump #'booleanp) '(1 nil "a" -4 b c t)) ;; => (1 nil t)
+(funcall (-orfn #'symbolp (-cut string-match-p "x" <>)) "axe") ;; => 1
+(funcall (-orfn #'= #'+) 1 1) ;; => t
```
#### -andfn `(&rest preds)`
-Take list of unary predicates `preds` and return a unary
-predicate with argument x that returns non-nil if all of the
-`preds` returns non-nil on x.
+Return a predicate that returns non-nil if all `preds` do so.
+The returned predicate `p` takes a variable number of arguments and
+passes them to each predicate in `preds` in turn. If any one of
+`preds` returns nil, `p` also returns nil without calling the
+remaining `preds`. If all `preds` return non-nil, `p` returns the last
+such value. If no `preds` are given, `p` always returns non-nil.
-In types: [a -> Bool] -> a -> Bool
+See also: [`-orfn`](#-orfn-rest-preds) and [`-not`](#-not-pred).
```el
-(funcall (-andfn (-cut < <> 10) 'even?) 6) ;; => t
-(funcall (-andfn (-cut < <> 10) 'even?) 12) ;; => nil
-(-filter (-andfn (-not 'even?) (-cut >= 5 <>)) '(1 2 3 4 5 6 7 8 9 10)) ;; =>
(1 3 5)
+(-filter (-andfn #'numberp (-cut < <> 5)) '(a 1 b 6 c 2)) ;; => (1 2)
+(mapcar (-andfn #'numberp #'1+) '(a 1 b 6)) ;; => (nil 2 nil 7)
+(funcall (-andfn #'= #'+) 1 1) ;; => 2
```
#### -iteratefn `(fn n)`
diff --git a/dash.el b/dash.el
index 6f97aca..a0be8f6 100644
--- a/dash.el
+++ b/dash.el
@@ -3113,24 +3113,73 @@ taking 1 argument which is a list of N arguments."
(declare (pure t) (side-effect-free t))
(lambda (args) (apply fn args)))
-(defun -on (operator transformer)
- "Return a function of two arguments that first applies
-TRANSFORMER to each of them and then applies OPERATOR on the
-results (in the same order).
+(defun -on (op trans)
+ "Return a function that calls TRANS on each arg and OP on the results.
+The returned function takes a variable number of arguments, calls
+the function TRANS on each one in turn, and then passes those
+results as the list of arguments to OP, in the same order.
-In types: (b -> b -> c) -> (a -> b) -> a -> a -> c"
- (lambda (x y) (funcall operator (funcall transformer x) (funcall transformer
y))))
+For example, the following pairs of expressions are morally
+equivalent:
-(defun -flip (func)
- "Swap the order of arguments for binary function FUNC.
-
-In types: (a -> b -> c) -> b -> a -> c"
- (lambda (x y) (funcall func y x)))
+ (funcall (-on #\\='+ #\\='1+) 1 2 3) = (+ (1+ 1) (1+ 2) (1+ 3))
+ (funcall (-on #\\='+ #\\='1+)) = (+)"
+ (declare (pure t) (side-effect-free t))
+ (lambda (&rest args)
+ ;; This unrolling seems to be a relatively cheap way to keep the
+ ;; overhead of `mapcar' + `apply' in check.
+ (cond ((cddr args)
+ (apply op (mapcar trans args)))
+ ((cdr args)
+ (funcall op (funcall trans (car args)) (funcall trans (cadr args))))
+ (args
+ (funcall op (funcall trans (car args))))
+ ((funcall op)))))
+
+(defun -flip (fn)
+ "Return a function that calls FN with its arguments reversed.
+The returned function takes the same number of arguments as FN.
+
+For example, the following two expressions are morally
+equivalent:
+
+ (funcall (-flip #\\='-) 1 2) = (- 2 1)
+
+See also: `-rotate-args'."
+ (declare (pure t) (side-effect-free t))
+ (lambda (&rest args) ;; Open-code for speed.
+ (cond ((cddr args) (apply fn (nreverse args)))
+ ((cdr args) (funcall fn (cadr args) (car args)))
+ (args (funcall fn (car args)))
+ ((funcall fn)))))
+
+(defun -rotate-args (n fn)
+ "Return a function that calls FN with args rotated N places to the right.
+The returned function takes the same number of arguments as FN,
+rotates the list of arguments N places to the right (left if N is
+negative) just like `-rotate', and applies FN to the result.
+
+See also: `-flip'."
+ (declare (pure t) (side-effect-free t))
+ (if (zerop n)
+ fn
+ (let ((even (= (% n 2) 0)))
+ (lambda (&rest args)
+ (cond ((cddr args) ;; Open-code for speed.
+ (apply fn (-rotate n args)))
+ ((cdr args)
+ (let ((fst (car args))
+ (snd (cadr args)))
+ (funcall fn (if even fst snd) (if even snd fst))))
+ (args
+ (funcall fn (car args)))
+ ((funcall fn)))))))
(defun -const (c)
"Return a function that returns C ignoring any additional arguments.
In types: a -> b -> a"
+ (declare (pure t) (side-effect-free t))
(lambda (&rest _) c))
(defmacro -cut (&rest params)
@@ -3147,30 +3196,51 @@ See SRFI-26 for detailed description."
`(lambda ,args
,(let ((body (--map (if (eq it '<>) (pop args) it) params)))
(if (eq (car params) '<>)
- (cons 'funcall body)
+ (cons #'funcall body)
body)))))
(defun -not (pred)
- "Take a unary predicate PRED and return a unary predicate
-that returns t if PRED returns nil and nil if PRED returns
-non-nil."
- (lambda (x) (not (funcall pred x))))
+ "Return a predicate that negates the result of PRED.
+The returned predicate passes its arguments to PRED. If PRED
+returns nil, the result is non-nil; otherwise the result is nil.
-(defun -orfn (&rest preds)
- "Take list of unary predicates PREDS and return a unary
-predicate with argument x that returns non-nil if at least one of
-the PREDS returns non-nil on x.
+See also: `-andfn' and `-orfn'."
+ (declare (pure t) (side-effect-free t))
+ (lambda (&rest args) (not (apply pred args))))
-In types: [a -> Bool] -> a -> Bool"
- (lambda (x) (-any? (-cut funcall <> x) preds)))
+(defun -orfn (&rest preds)
+ "Return a predicate that returns the first non-nil result of PREDS.
+The returned predicate takes a variable number of arguments,
+passes them to each predicate in PREDS in turn until one of them
+returns non-nil, and returns that non-nil result without calling
+the remaining PREDS. If all PREDS return nil, or if no PREDS are
+given, the returned predicate returns nil.
+
+See also: `-andfn' and `-not'."
+ (declare (pure t) (side-effect-free t))
+ ;; Open-code for speed.
+ (cond ((cdr preds) (lambda (&rest args) (--some (apply it args) preds)))
+ (preds (car preds))
+ (#'ignore)))
(defun -andfn (&rest preds)
- "Take list of unary predicates PREDS and return a unary
-predicate with argument x that returns non-nil if all of the
-PREDS returns non-nil on x.
-
-In types: [a -> Bool] -> a -> Bool"
- (lambda (x) (-all? (-cut funcall <> x) preds)))
+ "Return a predicate that returns non-nil if all PREDS do so.
+The returned predicate P takes a variable number of arguments and
+passes them to each predicate in PREDS in turn. If any one of
+PREDS returns nil, P also returns nil without calling the
+remaining PREDS. If all PREDS return non-nil, P returns the last
+such value. If no PREDS are given, P always returns non-nil.
+
+See also: `-orfn' and `-not'."
+ (declare (pure t) (side-effect-free t))
+ ;; Open-code for speed.
+ (cond ((cdr preds) (lambda (&rest args) (--every (apply it args) preds)))
+ (preds (car preds))
+ ;; As a `pure' function, this runtime check may generate
+ ;; backward-incompatible bytecode for `(-andfn)' at compile-time,
+ ;; but I doubt that's a problem in practice (famous last words).
+ ((fboundp 'always) #'always)
+ ((lambda (&rest _) t))))
(defun -iteratefn (fn n)
"Return a function FN composed N times with itself.
diff --git a/dash.texi b/dash.texi
index e7e0376..0d30090 100644
--- a/dash.texi
+++ b/dash.texi
@@ -4357,47 +4357,83 @@ taking 1 argument which is a list of @var{n} arguments.
@end defun
@anchor{-on}
-@defun -on (operator transformer)
-Return a function of two arguments that first applies
-@var{transformer} to each of them and then applies @var{operator} on the
-results (in the same order).
+@defun -on (op trans)
+Return a function that calls @var{trans} on each arg and @var{op} on the
results.
+The returned function takes a variable number of arguments, calls
+the function @var{trans} on each one in turn, and then passes those
+results as the list of arguments to @var{op}, in the same order.
-In types: (b -> b -> c) -> (a -> b) -> a -> a -> c
+For example, the following pairs of expressions are morally
+equivalent:
+
+ (funcall (-on #'+ #'1+) 1 2 3) = (+ (1+ 1) (1+ 2) (1+ 3))
+ (funcall (-on #'+ #'1+)) = (+)
@example
@group
-(-sort (-on '< 'length) '((1 2 3) (1) (1 2)))
+(-sort (-on #'< #'length) '((1 2 3) (1) (1 2)))
@result{} ((1) (1 2) (1 2 3))
@end group
@group
-(-min-by (-on '> 'length) '((1 2 3) (4) (1 2)))
- @result{} (4)
+(funcall (-on #'min #'string-to-number) "22" "2" "1" "12")
+ @result{} 1
@end group
@group
-(-min-by (-on 'string-lessp 'number-to-string) '(2 100 22))
- @result{} 22
+(-min-by (-on #'> #'length) '((1 2 3) (4) (1 2)))
+ @result{} (4)
@end group
@end example
@end defun
@anchor{-flip}
-@defun -flip (func)
-Swap the order of arguments for binary function @var{func}.
+@defun -flip (fn)
+Return a function that calls @var{fn} with its arguments reversed.
+The returned function takes the same number of arguments as @var{fn}.
+
+For example, the following two expressions are morally
+equivalent:
-In types: (a -> b -> c) -> b -> a -> c
+ (funcall (-flip #'-) 1 2) = (- 2 1)
+
+See also: @code{-rotate-args} (@pxref{-rotate-args}).
@example
@group
-(funcall (-flip '<) 2 1)
- @result{} t
+(-sort (-flip #'<) '(4 3 6 1))
+ @result{} (6 4 3 1)
@end group
@group
-(funcall (-flip '-) 3 8)
- @result{} 5
+(funcall (-flip #'-) 3 2 1 10)
+ @result{} 4
@end group
@group
-(-sort (-flip '<) '(4 3 6 1))
- @result{} (6 4 3 1)
+(funcall (-flip #'1+) 1)
+ @result{} 2
+@end group
+@end example
+@end defun
+
+@anchor{-rotate-args}
+@defun -rotate-args (n fn)
+Return a function that calls @var{fn} with args rotated @var{n} places to the
right.
+The returned function takes the same number of arguments as @var{fn},
+rotates the list of arguments @var{n} places to the right (left if @var{n} is
+negative) just like @code{-rotate} (@pxref{-rotate}), and applies @var{fn} to
the result.
+
+See also: @code{-flip} (@pxref{-flip}).
+
+@example
+@group
+(funcall (-rotate-args -1 #'list) 1 2 3 4)
+ @result{} (2 3 4 1)
+@end group
+@group
+(funcall (-rotate-args 1 #'-) 1 10 100)
+ @result{} 89
+@end group
+@group
+(funcall (-rotate-args 2 #'list) 3 4 5 1 2)
+ @result{} (1 2 3 4 5)
@end group
@end example
@end defun
@@ -4414,11 +4450,11 @@ In types: a -> b -> a
@result{} 2
@end group
@group
-(-map (-const 1) '("a" "b" "c" "d"))
+(mapcar (-const 1) '("a" "b" "c" "d"))
@result{} (1 1 1 1)
@end group
@group
-(-sum (-map (-const 1) '("a" "b" "c" "d")))
+(-sum (mapcar (-const 1) '("a" "b" "c" "d")))
@result{} 4
@end group
@end example
@@ -4449,17 +4485,23 @@ See @var{srfi-26} for detailed description.
@anchor{-not}
@defun -not (pred)
-Take a unary predicate @var{pred} and return a unary predicate
-that returns t if @var{pred} returns nil and nil if @var{pred} returns
-non-nil.
+Return a predicate that negates the result of @var{pred}.
+The returned predicate passes its arguments to @var{pred}. If @var{pred}
+returns nil, the result is non-nil; otherwise the result is nil.
+
+See also: @code{-andfn} (@pxref{-andfn}) and @code{-orfn} (@pxref{-orfn}).
@example
@group
-(funcall (-not 'even?) 5)
+(funcall (-not #'numberp) "5")
@result{} t
@end group
@group
-(-filter (-not (-partial '< 4)) '(1 2 3 4 5 6 7 8))
+(-sort (-not #'<) '(5 2 1 0 6))
+ @result{} (6 5 2 1 0)
+@end group
+@group
+(-filter (-not (-partial #'< 4)) '(1 2 3 4 5 6 7 8))
@result{} (1 2 3 4)
@end group
@end example
@@ -4467,19 +4509,26 @@ non-nil.
@anchor{-orfn}
@defun -orfn (&rest preds)
-Take list of unary predicates @var{preds} and return a unary
-predicate with argument x that returns non-nil if at least one of
-the @var{preds} returns non-nil on x.
+Return a predicate that returns the first non-nil result of @var{preds}.
+The returned predicate takes a variable number of arguments,
+passes them to each predicate in @var{preds} in turn until one of them
+returns non-nil, and returns that non-nil result without calling
+the remaining @var{preds}. If all @var{preds} return nil, or if no
@var{preds} are
+given, the returned predicate returns nil.
-In types: [a -> Bool] -> a -> Bool
+See also: @code{-andfn} (@pxref{-andfn}) and @code{-not} (@pxref{-not}).
@example
@group
-(-filter (-orfn 'even? (-partial (-flip '<) 5)) '(1 2 3 4 5 6 7 8 9 10))
- @result{} (1 2 3 4 6 8 10)
+(-filter (-orfn #'natnump #'booleanp) '(1 nil "a" -4 b c t))
+ @result{} (1 nil t)
+@end group
+@group
+(funcall (-orfn #'symbolp (-cut string-match-p "x" <>)) "axe")
+ @result{} 1
@end group
@group
-(funcall (-orfn 'stringp 'even?) "foo")
+(funcall (-orfn #'= #'+) 1 1)
@result{} t
@end group
@end example
@@ -4487,24 +4536,27 @@ In types: [a -> Bool] -> a -> Bool
@anchor{-andfn}
@defun -andfn (&rest preds)
-Take list of unary predicates @var{preds} and return a unary
-predicate with argument x that returns non-nil if all of the
-@var{preds} returns non-nil on x.
+Return a predicate that returns non-nil if all @var{preds} do so.
+The returned predicate @var{p} takes a variable number of arguments and
+passes them to each predicate in @var{preds} in turn. If any one of
+@var{preds} returns nil, @var{p} also returns nil without calling the
+remaining @var{preds}. If all @var{preds} return non-nil, @var{p} returns the
last
+such value. If no @var{preds} are given, @var{p} always returns non-nil.
-In types: [a -> Bool] -> a -> Bool
+See also: @code{-orfn} (@pxref{-orfn}) and @code{-not} (@pxref{-not}).
@example
@group
-(funcall (-andfn (-cut < <> 10) 'even?) 6)
- @result{} t
+(-filter (-andfn #'numberp (-cut < <> 5)) '(a 1 b 6 c 2))
+ @result{} (1 2)
@end group
@group
-(funcall (-andfn (-cut < <> 10) 'even?) 12)
- @result{} nil
+(mapcar (-andfn #'numberp #'1+) '(a 1 b 6))
+ @result{} (nil 2 nil 7)
@end group
@group
-(-filter (-andfn (-not 'even?) (-cut >= 5 <>)) '(1 2 3 4 5 6 7 8 9 10))
- @result{} (1 3 5)
+(funcall (-andfn #'= #'+) 1 1)
+ @result{} 2
@end group
@end example
@end defun
diff --git a/dev/examples.el b/dev/examples.el
index d5d5210..0125da2 100644
--- a/dev/examples.el
+++ b/dev/examples.el
@@ -871,15 +871,15 @@ value rather than consuming a list to produce a single
value."
(-partition-after-pred #'booleanp '(t)) => '((t))
(-partition-after-pred #'booleanp '(0 t)) => '((0 t))
(--partition-after-pred (= (% it 2) 0) '()) => '()
- (--partition-after-pred (= (% it 2) 1) '()) => '()
+ (--partition-after-pred (= (mod it 2) 1) '()) => '()
(--partition-after-pred (= (% it 2) 0) '(0)) => '((0))
- (--partition-after-pred (= (% it 2) 1) '(0)) => '((0))
+ (--partition-after-pred (= (mod it 2) 1) '(0)) => '((0))
(--partition-after-pred (= (% it 2) 0) '(0 1)) => '((0) (1))
- (--partition-after-pred (= (% it 2) 1) '(0 1)) => '((0 1))
+ (--partition-after-pred (= (mod it 2) 1) '(0 1)) => '((0 1))
(--partition-after-pred (= (% it 2) 0) '(0 1 2)) => '((0) (1 2))
- (--partition-after-pred (= (% it 2) 1) '(0 1 2)) => '((0 1) (2))
+ (--partition-after-pred (= (mod it 2) 1) '(0 1 2)) => '((0 1) (2))
(--partition-after-pred (= (% it 2) 0) '(0 1 2 3)) => '((0) (1 2) (3))
- (--partition-after-pred (= (% it 2) 1) '(0 1 2 3)) => '((0 1) (2 3))
+ (--partition-after-pred (= (mod it 2) 1) '(0 1 2 3)) => '((0 1) (2 3))
(--partition-after-pred t '()) => ()
(--partition-after-pred t '(0)) => '((0))
(--partition-after-pred t '(0 1)) => '((0) (1))
@@ -1055,7 +1055,9 @@ related predicates."
(-cons*) => ()
(-cons* ()) => ()
(-cons* 1 ()) => '(1)
- (-cons* 1 '(2)) => '(1 2))
+ (-cons* 1 '(2)) => '(1 2)
+ ;; Assert that &rest conses a fresh list in case that ever changes.
+ (let ((l (list 1 2))) (apply #'-cons* l) l) => '(1 2))
(defexamples -snoc
(-snoc '(1 2 3) 4) => '(1 2 3 4)
@@ -1769,30 +1771,83 @@ or readability."
=> '((1 (1)) (1 (2)) (5 (5))))
(defexamples -on
- (-sort (-on '< 'length) '((1 2 3) (1) (1 2))) => '((1) (1 2) (1 2 3))
- (-min-by (-on '> 'length) '((1 2 3) (4) (1 2))) => '(4)
- (-min-by (-on 'string-lessp 'number-to-string) '(2 100 22)) => 22
- (-max-by (-on '> 'car) '((2 2 3) (3) (1 2))) => '(3)
- (-sort (-on 'string-lessp 'number-to-string) '(10 12 1 2 22)) => '(1 10 12
2 22)
- (funcall (-on '+ '1+) 1 2) => 5
- (funcall (-on '+ 'identity) 1 2) => 3
- (funcall (-on '* 'length) '(1 2 3) '(4 5)) => 6
- (funcall (-on (-on '+ 'length) 'cdr) '(1 2 3) '(4 5)) => 3
- (funcall (-on '+ (lambda (x) (length (cdr x)))) '(1 2 3) '(4 5)) => 3
- (-sort (-on '< 'car) '((3 2 5) (2) (1 2))) => '((1 2) (2) (3 2 5))
- (-sort (-on '< (lambda (x) (length x))) '((1 2 3) (1) (1 2))) => '((1) (1
2) (1 2 3))
- (-sort (-on (-on '< 'car) 'cdr) '((0 3) (2 1) (4 2 8))) => '((2 1) (4 2 8)
(0 3))
- (-sort (-on '< 'cadr) '((0 3) (2 1) (4 2 8))) => '((2 1) (4 2 8) (0 3)))
+ (-sort (-on #'< #'length) '((1 2 3) (1) (1 2))) => '((1) (1 2) (1 2 3))
+ (funcall (-on #'min #'string-to-number) "22" "2" "1" "12") => 1
+ (-min-by (-on #'> #'length) '((1 2 3) (4) (1 2))) => '(4)
+ (-min-by (-on #'string< #'number-to-string) '(2 100 22)) => 22
+ (-max-by (-on #'> #'car) '((2 2 3) (3) (1 2))) => '(3)
+ (-sort (-on #'string< #'number-to-string) '(12 1 2 22)) => '(1 12 2 22)
+ (funcall (-on #'+ #'1+) 1 2) => 5
+ (funcall (-on #'+ #'identity) 1 2) => 3
+ (funcall (-on #'* #'length) '(1 2 3) '(4 5)) => 6
+ (funcall (-on (-on #'+ #'length) #'cdr) '(1 2 3) '(4 5)) => 3
+ (funcall (-on #'+ (lambda (x) (length (cdr x)))) '(1 2 3) '(4 5)) => 3
+ (-sort (-on #'< #'car) '((3 2 5) (2) (1 2))) => '((1 2) (2) (3 2 5))
+ (-sort (-on #'< (lambda (x) (length x))) '((1 2 3) (1) (1 2)))
+ => '((1) (1 2) (1 2 3))
+ (-sort (-on (-on #'< #'car) #'cdr) '((0 3) (2 1) (4 2 8)))
+ => '((2 1) (4 2 8) (0 3))
+ (-sort (-on #'< #'cadr) '((0 3) (2 1) (4 2 8))) => '((2 1) (4 2 8) (0 3))
+ (funcall (-on #'not #'not) nil) => nil
+ (funcall (-on #'+ #'1+) 1 10 100 1000) => 1115
+ (funcall (-on #'+ #'1+) 1 10 100) => 114
+ (funcall (-on #'+ #'1+) 1 10) => 13
+ (funcall (-on #'+ #'1+) 1) => 2
+ (funcall (-on #'+ #'1+)) => 0
+ (funcall (-on #'1+ #'1+) 0) => 2
+ (funcall (-on #'+ #'*)) => 0
+ (funcall (-on #'* #'+)) => 1)
(defexamples -flip
- (funcall (-flip '<) 2 1) => t
- (funcall (-flip '-) 3 8) => 5
- (-sort (-flip '<) '(4 3 6 1)) => '(6 4 3 1))
+ (-sort (-flip #'<) '(4 3 6 1)) => '(6 4 3 1)
+ (funcall (-flip #'-) 3 2 1 10) => 4
+ (funcall (-flip #'1+) 1) => 2
+ (funcall (-flip #'<) 2 1) => t
+ (funcall (-flip #'list) 1 2 3) => '(3 2 1)
+ (funcall (-flip #'list) 1 2) => '(2 1)
+ (funcall (-flip #'list) 1) => '(1)
+ (funcall (-flip #'list)) => '()
+ ;; Assert that &rest conses a fresh list in case that ever changes.
+ (let ((a (list 1 2 3 4))) (apply (-flip #'-) a) a) => '(1 2 3 4))
+
+ (defexamples -rotate-args
+ (funcall (-rotate-args -1 #'list) 1 2 3 4) => '(2 3 4 1)
+ (funcall (-rotate-args 1 #'-) 1 10 100) => 89
+ (funcall (-rotate-args 2 #'list) 3 4 5 1 2) => '(1 2 3 4 5)
+ (funcall (-rotate-args -2 #'list) 1 2 3 4) => '(3 4 1 2)
+ (funcall (-rotate-args 0 #'list) 1 2 3 4) => '(1 2 3 4)
+ (funcall (-rotate-args 1 #'list) 1 2 3 4) => '(4 1 2 3)
+ (funcall (-rotate-args 2 #'list) 1 2 3 4) => '(3 4 1 2)
+ (funcall (-rotate-args -2 #'list) 1 2 3) => '(3 1 2)
+ (funcall (-rotate-args -1 #'list) 1 2 3) => '(2 3 1)
+ (funcall (-rotate-args 0 #'list) 1 2 3) => '(1 2 3)
+ (funcall (-rotate-args 1 #'list) 1 2 3) => '(3 1 2)
+ (funcall (-rotate-args 2 #'list) 1 2 3) => '(2 3 1)
+ (funcall (-rotate-args -2 #'list) 1 2) => '(1 2)
+ (funcall (-rotate-args -1 #'list) 1 2) => '(2 1)
+ (funcall (-rotate-args 0 #'list) 1 2) => '(1 2)
+ (funcall (-rotate-args 1 #'list) 1 2) => '(2 1)
+ (funcall (-rotate-args 2 #'list) 1 2) => '(1 2)
+ (funcall (-rotate-args -2 #'list) 1) => '(1)
+ (funcall (-rotate-args -1 #'list) 1) => '(1)
+ (funcall (-rotate-args 0 #'list) 1) => '(1)
+ (funcall (-rotate-args 1 #'list) 1) => '(1)
+ (funcall (-rotate-args 2 #'list) 1) => '(1)
+ (funcall (-rotate-args -2 #'list)) => '()
+ (funcall (-rotate-args -1 #'list)) => '()
+ (funcall (-rotate-args 0 #'list)) => '()
+ (funcall (-rotate-args 1 #'list)) => '()
+ (funcall (-rotate-args 2 #'list)) => '()
+ (let ((a (list 1 2 3))) (apply (-rotate-args 2 #'-) a) a) => '(1 2 3))
(defexamples -const
(funcall (-const 2) 1 3 "foo") => 2
- (-map (-const 1) '("a" "b" "c" "d")) => '(1 1 1 1)
- (-sum (-map (-const 1) '("a" "b" "c" "d"))) => 4)
+ (mapcar (-const 1) '("a" "b" "c" "d")) => '(1 1 1 1)
+ (-sum (mapcar (-const 1) '("a" "b" "c" "d"))) => 4
+ (funcall (-const t)) => t
+ (funcall (-const nil)) => nil
+ (funcall (-const t) nil) => t
+ (funcall (-const nil) nil) => nil)
(defexamples -cut
(funcall (-cut list 1 <> 3 <> 5) 2 4) => '(1 2 3 4 5)
@@ -1801,17 +1856,57 @@ or readability."
(-filter (-cut < <> 5) '(1 3 5 7 9)) => '(1 3))
(defexamples -not
- (funcall (-not 'even?) 5) => t
- (-filter (-not (-partial '< 4)) '(1 2 3 4 5 6 7 8)) => '(1 2 3 4))
+ (funcall (-not #'numberp) "5") => t
+ (-sort (-not #'<) '(5 2 1 0 6)) => '(6 5 2 1 0)
+ (-filter (-not (-partial #'< 4)) '(1 2 3 4 5 6 7 8)) => '(1 2 3 4)
+ ;; Variadic `<' was introduced in Emacs 24.4.
+ (funcall (-not (lambda (a b c) (and (< a b) (< b c)))) 1 2 3) => nil
+ (funcall (-not (lambda (a b c) (and (< a b) (< b c)))) 3 2 1) => t
+ (funcall (-not #'<) 1 2) => nil
+ (funcall (-not #'<) 2 1) => t
+ (funcall (-not #'+) 1) => nil
+ (funcall (-not #'+)) => nil)
(defexamples -orfn
- (-filter (-orfn 'even? (-partial (-flip '<) 5)) '(1 2 3 4 5 6 7 8 9 10))
=> '(1 2 3 4 6 8 10)
- (funcall (-orfn 'stringp 'even?) "foo") => t)
+ (-filter (-orfn #'natnump #'booleanp) '(1 nil "a" -4 b c t)) => '(1 nil t)
+ (funcall (-orfn #'symbolp (-cut string-match-p "x" <>)) "axe") => 1
+ (funcall (-orfn #'= #'+) 1 1) => t
+ (funcall (-orfn #'+ #'null)) => 0
+ (funcall (-orfn #'+ #'null) 1) => 1
+ (funcall (-orfn #'+ #'null) 1 2) => 3
+ (funcall (-orfn #'+ #'null) 1 2 3) => 6
+ (funcall (-orfn #'ignore #'+)) => 0
+ (funcall (-orfn #'ignore #'+) 1) => 1
+ (funcall (-orfn #'ignore #'+) 1 2) => 3
+ (funcall (-orfn #'ignore #'+) 1 2 3) => 6
+ (-filter (-orfn #'symbolp) '(a b 1 nil t 2)) => '(a b nil t)
+ (-filter (-orfn #'null) '(a b 1 nil t 2)) => '(nil)
+ (-filter (-orfn) '(nil t)) => '()
+ (-orfn #'null) => #'null
+ (-orfn) => #'ignore)
(defexamples -andfn
- (funcall (-andfn (-cut < <> 10) 'even?) 6) => t
- (funcall (-andfn (-cut < <> 10) 'even?) 12) => nil
- (-filter (-andfn (-not 'even?) (-cut >= 5 <>)) '(1 2 3 4 5 6 7 8 9 10)) =>
'(1 3 5))
+ (-filter (-andfn #'numberp (-cut < <> 5)) '(a 1 b 6 c 2)) => '(1 2)
+ (mapcar (-andfn #'numberp #'1+) '(a 1 b 6)) => '(nil 2 nil 7)
+ (funcall (-andfn #'= #'+) 1 1) => 2
+ (funcall (-andfn #'ignore #'+)) => nil
+ (funcall (-andfn #'ignore #'+) 1) => nil
+ (funcall (-andfn #'ignore #'+) 1 2) => nil
+ (funcall (-andfn #'+ #'ignore)) => nil
+ (funcall (-andfn #'+ #'ignore) 1) => nil
+ (funcall (-andfn #'+ #'ignore) 1 2) => nil
+ (funcall (-andfn #'+ #'list)) => '()
+ (funcall (-andfn #'+ #'list) 1) => '(1)
+ (funcall (-andfn #'+ #'list) 1 2) => '(1 2)
+ (funcall (-andfn #'list #'+)) => nil
+ (funcall (-andfn #'list #'+) 1) => 1
+ (funcall (-andfn #'list #'+) 1 2) => 3
+ (funcall (-andfn #'* #'+)) => 0
+ (funcall (-andfn #'+ #'*)) => 1
+ (-andfn #'null) => #'null
+ (funcall (-andfn)) => t
+ (funcall (-andfn) nil) => t
+ (funcall (-andfn) t) => t)
(defexamples -iteratefn
(funcall (-iteratefn (lambda (x) (* x x)) 3) 2) => 256
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [elpa] externals/dash 11a6296 1/2: Prefer n-ary over unary/binary combinators,
ELPA Syncer <=