Merge PR #308 from basil-conto/blc/variadic

Closes: #72, #306.
master
Basil L. Contovounesios 5 years ago
commit 350b4c3867
No known key found for this signature in database
GPG Key ID: 205AB54A5D5D8CFF
  1. 4
      NEWS.md
  2. 113
      README.md
  3. 126
      dash.el
  4. 138
      dash.texi
  5. 159
      dev/examples.el

@ -18,6 +18,10 @@ See the end of the file for license conditions.
#### New features #### 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`. - New function `-every` and its anaphoric macro counterpart `--every`.
They are like the existing `-every-p` and `--every-p`, respectively, They are like the existing `-every-p` and `--every-p`, respectively,
but return the last non-`nil` result instead of just `t`. but return the last non-`nil` result instead of just `t`.

@ -373,8 +373,9 @@ Functions that manipulate and compose other functions.
* [`-juxt`](#-juxt-rest-fns) `(&rest fns)` * [`-juxt`](#-juxt-rest-fns) `(&rest fns)`
* [`-compose`](#-compose-rest-fns) `(&rest fns)` * [`-compose`](#-compose-rest-fns) `(&rest fns)`
* [`-applify`](#-applify-fn) `(fn)` * [`-applify`](#-applify-fn) `(fn)`
* [`-on`](#-on-operator-transformer) `(operator transformer)` * [`-on`](#-on-op-trans) `(op trans)`
* [`-flip`](#-flip-func) `(func)` * [`-flip`](#-flip-fn) `(fn)`
* [`-rotate-args`](#-rotate-args-n-fn) `(n fn)`
* [`-const`](#-const-c) `(c)` * [`-const`](#-const-c) `(c)`
* [`-cut`](#-cut-rest-params) `(&rest params)` * [`-cut`](#-cut-rest-params) `(&rest params)`
* [`-not`](#-not-pred) `(pred)` * [`-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 Take a comparison function `comparator` and a `list` and return
the least element of the list by the comparison function. 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. comparing them.
```el ```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 Take a comparison function `comparator` and a `list` and return
the greatest element of the list by the comparison function. 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. comparing them.
```el ```el
@ -2892,30 +2893,56 @@ taking 1 argument which is a list of `n` arguments.
(funcall (-applify #'<) '(3 6)) ;; => t (funcall (-applify #'<) '(3 6)) ;; => t
``` ```
#### -on `(operator transformer)` #### -on `(op trans)`
Return a function of two arguments that first applies Return a function that calls `trans` on each arg and `op` on the results.
`transformer` to each of them and then applies `operator` on the The returned function takes a variable number of arguments, calls
results (in the same order). 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 ```el
(-sort (-on '< 'length) '((1 2 3) (1) (1 2))) ;; => ((1) (1 2) (1 2 3)) (-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) (funcall (-on #'min #'string-to-number) "22" "2" "1" "12") ;; => 1
(-min-by (-on 'string-lessp 'number-to-string) '(2 100 22)) ;; => 22 (-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 ```el
(funcall (-flip '<) 2 1) ;; => t (-sort (-flip #'<) '(4 3 6 1)) ;; => (6 4 3 1)
(funcall (-flip '-) 3 8) ;; => 5 (funcall (-flip #'-) 3 2 1 10) ;; => 4
(-sort (-flip '<) '(4 3 6 1)) ;; => (6 4 3 1) (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)` #### -const `(c)`
@ -2926,8 +2953,8 @@ In types: a -> b -> a
```el ```el
(funcall (-const 2) 1 3 "foo") ;; => 2 (funcall (-const 2) 1 3 "foo") ;; => 2
(-map (-const 1) '("a" "b" "c" "d")) ;; => (1 1 1 1) (mapcar (-const 1) '("a" "b" "c" "d")) ;; => (1 1 1 1)
(-sum (-map (-const 1) '("a" "b" "c" "d"))) ;; => 4 (-sum (mapcar (-const 1) '("a" "b" "c" "d"))) ;; => 4
``` ```
#### -cut `(&rest params)` #### -cut `(&rest params)`
@ -2945,40 +2972,50 @@ See `srfi-26` for detailed description.
#### -not `(pred)` #### -not `(pred)`
Take a unary predicate `pred` and return a unary predicate Return a predicate that negates the result of `pred`.
that returns t if `pred` returns nil and nil if `pred` returns The returned predicate passes its arguments to `pred`. If `pred`
non-nil. returns nil, the result is non-nil; otherwise the result is nil.
See also: [`-andfn`](#-andfn-rest-preds) and [`-orfn`](#-orfn-rest-preds).
```el ```el
(funcall (-not 'even?) 5) ;; => t (funcall (-not #'numberp) "5") ;; => t
(-filter (-not (-partial '< 4)) '(1 2 3 4 5 6 7 8)) ;; => (1 2 3 4) (-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)` #### -orfn `(&rest preds)`
Take list of unary predicates `preds` and return a unary Return a predicate that returns the first non-nil result of `preds`.
predicate with argument x that returns non-nil if at least one of The returned predicate takes a variable number of arguments,
the `preds` returns non-nil on x. 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 ```el
(-filter (-orfn 'even? (-partial (-flip '<) 5)) '(1 2 3 4 5 6 7 8 9 10)) ;; => (1 2 3 4 6 8 10) (-filter (-orfn #'natnump #'booleanp) '(1 nil "a" -4 b c t)) ;; => (1 nil t)
(funcall (-orfn 'stringp 'even?) "foo") ;; => t (funcall (-orfn #'symbolp (-cut string-match-p "x" <>)) "axe") ;; => 1
(funcall (-orfn #'= #'+) 1 1) ;; => t
``` ```
#### -andfn `(&rest preds)` #### -andfn `(&rest preds)`
Take list of unary predicates `preds` and return a unary Return a predicate that returns non-nil if all `preds` do so.
predicate with argument x that returns non-nil if all of the The returned predicate `p` takes a variable number of arguments and
`preds` returns non-nil on x. 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 ```el
(funcall (-andfn (-cut < <> 10) 'even?) 6) ;; => t (-filter (-andfn #'numberp (-cut < <> 5)) '(a 1 b 6 c 2)) ;; => (1 2)
(funcall (-andfn (-cut < <> 10) 'even?) 12) ;; => nil (mapcar (-andfn #'numberp #'1+) '(a 1 b 6)) ;; => (nil 2 nil 7)
(-filter (-andfn (-not 'even?) (-cut >= 5 <>)) '(1 2 3 4 5 6 7 8 9 10)) ;; => (1 3 5) (funcall (-andfn #'= #'+) 1 1) ;; => 2
``` ```
#### -iteratefn `(fn n)` #### -iteratefn `(fn n)`

@ -3113,24 +3113,73 @@ taking 1 argument which is a list of N arguments."
(declare (pure t) (side-effect-free t)) (declare (pure t) (side-effect-free t))
(lambda (args) (apply fn args))) (lambda (args) (apply fn args)))
(defun -on (operator transformer) (defun -on (op trans)
"Return a function of two arguments that first applies "Return a function that calls TRANS on each arg and OP on the results.
TRANSFORMER to each of them and then applies OPERATOR on the The returned function takes a variable number of arguments, calls
results (in the same order). 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
(lambda (x y) (funcall operator (funcall transformer x) (funcall transformer y)))) equivalent:
(defun -flip (func) (funcall (-on #\\='+ #\\='1+) 1 2 3) = (+ (1+ 1) (1+ 2) (1+ 3))
"Swap the order of arguments for binary function FUNC. (funcall (-on #\\='+ #\\='1+)) = (+)"
(declare (pure t) (side-effect-free t))
In types: (a -> b -> c) -> b -> a -> c" (lambda (&rest args)
(lambda (x y) (funcall func y x))) ;; 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) (defun -const (c)
"Return a function that returns C ignoring any additional arguments. "Return a function that returns C ignoring any additional arguments.
In types: a -> b -> a" In types: a -> b -> a"
(declare (pure t) (side-effect-free t))
(lambda (&rest _) c)) (lambda (&rest _) c))
(defmacro -cut (&rest params) (defmacro -cut (&rest params)
@ -3147,30 +3196,51 @@ See SRFI-26 for detailed description."
`(lambda ,args `(lambda ,args
,(let ((body (--map (if (eq it '<>) (pop args) it) params))) ,(let ((body (--map (if (eq it '<>) (pop args) it) params)))
(if (eq (car params) '<>) (if (eq (car params) '<>)
(cons 'funcall body) (cons #'funcall body)
body))))) body)))))
(defun -not (pred) (defun -not (pred)
"Take a unary predicate PRED and return a unary predicate "Return a predicate that negates the result of PRED.
that returns t if PRED returns nil and nil if PRED returns The returned predicate passes its arguments to PRED. If PRED
non-nil." returns nil, the result is non-nil; otherwise the result is nil.
(lambda (x) (not (funcall pred x))))
(defun -orfn (&rest preds) See also: `-andfn' and `-orfn'."
"Take list of unary predicates PREDS and return a unary (declare (pure t) (side-effect-free t))
predicate with argument x that returns non-nil if at least one of (lambda (&rest args) (not (apply pred args))))
the PREDS returns non-nil on x.
In types: [a -> Bool] -> a -> Bool" (defun -orfn (&rest preds)
(lambda (x) (-any? (-cut funcall <> x) 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) (defun -andfn (&rest preds)
"Take list of unary predicates PREDS and return a unary "Return a predicate that returns non-nil if all PREDS do so.
predicate with argument x that returns non-nil if all of the The returned predicate P takes a variable number of arguments and
PREDS returns non-nil on x. passes them to each predicate in PREDS in turn. If any one of
PREDS returns nil, P also returns nil without calling the
In types: [a -> Bool] -> a -> Bool" remaining PREDS. If all PREDS return non-nil, P returns the last
(lambda (x) (-all? (-cut funcall <> x) preds))) 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) (defun -iteratefn (fn n)
"Return a function FN composed N times with itself. "Return a function FN composed N times with itself.

@ -4357,47 +4357,83 @@ taking 1 argument which is a list of @var{n} arguments.
@end defun @end defun
@anchor{-on} @anchor{-on}
@defun -on (operator transformer) @defun -on (op trans)
Return a function of two arguments that first applies Return a function that calls @var{trans} on each arg and @var{op} on the results.
@var{transformer} to each of them and then applies @var{operator} on the The returned function takes a variable number of arguments, calls
results (in the same order). 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 @example
@group @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)) @result{} ((1) (1 2) (1 2 3))
@end group @end group
@group @group
(-min-by (-on '> 'length) '((1 2 3) (4) (1 2))) (funcall (-on #'min #'string-to-number) "22" "2" "1" "12")
@result{} (4) @result{} 1
@end group @end group
@group @group
(-min-by (-on 'string-lessp 'number-to-string) '(2 100 22)) (-min-by (-on #'> #'length) '((1 2 3) (4) (1 2)))
@result{} 22 @result{} (4)
@end group @end group
@end example @end example
@end defun @end defun
@anchor{-flip} @anchor{-flip}
@defun -flip (func) @defun -flip (fn)
Swap the order of arguments for binary function @var{func}. 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 @example
@group @group
(funcall (-flip '<) 2 1) (-sort (-flip #'<) '(4 3 6 1))
@result{} t @result{} (6 4 3 1)
@end group @end group
@group @group
(funcall (-flip '-) 3 8) (funcall (-flip #'-) 3 2 1 10)
@result{} 5 @result{} 4
@end group @end group
@group @group
(-sort (-flip '<) '(4 3 6 1)) (funcall (-flip #'1+) 1)
@result{} (6 4 3 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 group
@end example @end example
@end defun @end defun
@ -4414,11 +4450,11 @@ In types: a -> b -> a
@result{} 2 @result{} 2
@end group @end group
@group @group
(-map (-const 1) '("a" "b" "c" "d")) (mapcar (-const 1) '("a" "b" "c" "d"))
@result{} (1 1 1 1) @result{} (1 1 1 1)
@end group @end group
@group @group
(-sum (-map (-const 1) '("a" "b" "c" "d"))) (-sum (mapcar (-const 1) '("a" "b" "c" "d")))
@result{} 4 @result{} 4
@end group @end group
@end example @end example
@ -4449,17 +4485,23 @@ See @var{srfi-26} for detailed description.
@anchor{-not} @anchor{-not}
@defun -not (pred) @defun -not (pred)
Take a unary predicate @var{pred} and return a unary predicate Return a predicate that negates the result of @var{pred}.
that returns t if @var{pred} returns nil and nil if @var{pred} returns The returned predicate passes its arguments to @var{pred}. If @var{pred}
non-nil. returns nil, the result is non-nil; otherwise the result is nil.
See also: @code{-andfn} (@pxref{-andfn}) and @code{-orfn} (@pxref{-orfn}).
@example @example
@group @group
(funcall (-not 'even?) 5) (funcall (-not #'numberp) "5")
@result{} t @result{} t
@end group @end group
@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) @result{} (1 2 3 4)
@end group @end group
@end example @end example
@ -4467,19 +4509,26 @@ non-nil.
@anchor{-orfn} @anchor{-orfn}
@defun -orfn (&rest preds) @defun -orfn (&rest preds)
Take list of unary predicates @var{preds} and return a unary Return a predicate that returns the first non-nil result of @var{preds}.
predicate with argument x that returns non-nil if at least one of The returned predicate takes a variable number of arguments,
the @var{preds} returns non-nil on x. 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 @example
@group @group
(-filter (-orfn 'even? (-partial (-flip '<) 5)) '(1 2 3 4 5 6 7 8 9 10)) (-filter (-orfn #'natnump #'booleanp) '(1 nil "a" -4 b c t))
@result{} (1 2 3 4 6 8 10) @result{} (1 nil t)
@end group
@group
(funcall (-orfn #'symbolp (-cut string-match-p "x" <>)) "axe")
@result{} 1
@end group @end group
@group @group
(funcall (-orfn 'stringp 'even?) "foo") (funcall (-orfn #'= #'+) 1 1)
@result{} t @result{} t
@end group @end group
@end example @end example
@ -4487,24 +4536,27 @@ In types: [a -> Bool] -> a -> Bool
@anchor{-andfn} @anchor{-andfn}
@defun -andfn (&rest preds) @defun -andfn (&rest preds)
Take list of unary predicates @var{preds} and return a unary Return a predicate that returns non-nil if all @var{preds} do so.
predicate with argument x that returns non-nil if all of the The returned predicate @var{p} takes a variable number of arguments and
@var{preds} returns non-nil on x. 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 @example
@group @group
(funcall (-andfn (-cut < <> 10) 'even?) 6) (-filter (-andfn #'numberp (-cut < <> 5)) '(a 1 b 6 c 2))
@result{} t @result{} (1 2)
@end group @end group
@group @group
(funcall (-andfn (-cut < <> 10) 'even?) 12) (mapcar (-andfn #'numberp #'1+) '(a 1 b 6))
@result{} nil @result{} (nil 2 nil 7)
@end group @end group
@group @group
(-filter (-andfn (-not 'even?) (-cut >= 5 <>)) '(1 2 3 4 5 6 7 8 9 10)) (funcall (-andfn #'= #'+) 1 1)
@result{} (1 3 5) @result{} 2
@end group @end group
@end example @end example
@end defun @end defun

@ -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 '(t)) => '((t))
(-partition-after-pred #'booleanp '(0 t)) => '((0 t)) (-partition-after-pred #'booleanp '(0 t)) => '((0 t))
(--partition-after-pred (= (% it 2) 0) '()) => '() (--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) 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) 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) 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) 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 '()) => ()
(--partition-after-pred t '(0)) => '((0)) (--partition-after-pred t '(0)) => '((0))
(--partition-after-pred t '(0 1)) => '((0) (1)) (--partition-after-pred t '(0 1)) => '((0) (1))
@ -1055,7 +1055,9 @@ related predicates."
(-cons*) => () (-cons*) => ()
(-cons* ()) => () (-cons* ()) => ()
(-cons* 1 ()) => '(1) (-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 (defexamples -snoc
(-snoc '(1 2 3) 4) => '(1 2 3 4) (-snoc '(1 2 3) 4) => '(1 2 3 4)
@ -1769,30 +1771,83 @@ or readability."
=> '((1 (1)) (1 (2)) (5 (5)))) => '((1 (1)) (1 (2)) (5 (5))))
(defexamples -on (defexamples -on
(-sort (-on '< 'length) '((1 2 3) (1) (1 2))) => '((1) (1 2) (1 2 3)) (-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) (funcall (-on #'min #'string-to-number) "22" "2" "1" "12") => 1
(-min-by (-on 'string-lessp 'number-to-string) '(2 100 22)) => 22 (-min-by (-on #'> #'length) '((1 2 3) (4) (1 2))) => '(4)
(-max-by (-on '> 'car) '((2 2 3) (3) (1 2))) => '(3) (-min-by (-on #'string< #'number-to-string) '(2 100 22)) => 22
(-sort (-on 'string-lessp 'number-to-string) '(10 12 1 2 22)) => '(1 10 12 2 22) (-max-by (-on #'> #'car) '((2 2 3) (3) (1 2))) => '(3)
(funcall (-on '+ '1+) 1 2) => 5 (-sort (-on #'string< #'number-to-string) '(12 1 2 22)) => '(1 12 2 22)
(funcall (-on '+ 'identity) 1 2) => 3 (funcall (-on #'+ #'1+) 1 2) => 5
(funcall (-on '* 'length) '(1 2 3) '(4 5)) => 6 (funcall (-on #'+ #'identity) 1 2) => 3
(funcall (-on (-on '+ 'length) 'cdr) '(1 2 3) '(4 5)) => 3 (funcall (-on #'* #'length) '(1 2 3) '(4 5)) => 6
(funcall (-on '+ (lambda (x) (length (cdr x)))) '(1 2 3) '(4 5)) => 3 (funcall (-on (-on #'+ #'length) #'cdr) '(1 2 3) '(4 5)) => 3
(-sort (-on '< 'car) '((3 2 5) (2) (1 2))) => '((1 2) (2) (3 2 5)) (funcall (-on #'+ (lambda (x) (length (cdr x)))) '(1 2 3) '(4 5)) => 3
(-sort (-on '< (lambda (x) (length x))) '((1 2 3) (1) (1 2))) => '((1) (1 2) (1 2 3)) (-sort (-on #'< #'car) '((3 2 5) (2) (1 2))) => '((1 2) (2) (3 2 5))
(-sort (-on (-on '< 'car) 'cdr) '((0 3) (2 1) (4 2 8))) => '((2 1) (4 2 8) (0 3)) (-sort (-on #'< (lambda (x) (length x))) '((1 2 3) (1) (1 2)))
(-sort (-on '< 'cadr) '((0 3) (2 1) (4 2 8))) => '((2 1) (4 2 8) (0 3))) => '((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 (defexamples -flip
(funcall (-flip '<) 2 1) => t (-sort (-flip #'<) '(4 3 6 1)) => '(6 4 3 1)
(funcall (-flip '-) 3 8) => 5 (funcall (-flip #'-) 3 2 1 10) => 4
(-sort (-flip '<) '(4 3 6 1)) => '(6 4 3 1)) (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 (defexamples -const
(funcall (-const 2) 1 3 "foo") => 2 (funcall (-const 2) 1 3 "foo") => 2
(-map (-const 1) '("a" "b" "c" "d")) => '(1 1 1 1) (mapcar (-const 1) '("a" "b" "c" "d")) => '(1 1 1 1)
(-sum (-map (-const 1) '("a" "b" "c" "d"))) => 4) (-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 (defexamples -cut
(funcall (-cut list 1 <> 3 <> 5) 2 4) => '(1 2 3 4 5) (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)) (-filter (-cut < <> 5) '(1 3 5 7 9)) => '(1 3))
(defexamples -not (defexamples -not
(funcall (-not 'even?) 5) => t (funcall (-not #'numberp) "5") => t
(-filter (-not (-partial '< 4)) '(1 2 3 4 5 6 7 8)) => '(1 2 3 4)) (-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 (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) (-filter (-orfn #'natnump #'booleanp) '(1 nil "a" -4 b c t)) => '(1 nil t)
(funcall (-orfn 'stringp 'even?) "foo") => 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 (defexamples -andfn
(funcall (-andfn (-cut < <> 10) 'even?) 6) => t (-filter (-andfn #'numberp (-cut < <> 5)) '(a 1 b 6 c 2)) => '(1 2)
(funcall (-andfn (-cut < <> 10) 'even?) 12) => nil (mapcar (-andfn #'numberp #'1+) '(a 1 b 6)) => '(nil 2 nil 7)
(-filter (-andfn (-not 'even?) (-cut >= 5 <>)) '(1 2 3 4 5 6 7 8 9 10)) => '(1 3 5)) (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 (defexamples -iteratefn
(funcall (-iteratefn (lambda (x) (* x x)) 3) 2) => 256 (funcall (-iteratefn (lambda (x) (* x x)) 3) 2) => 256

Loading…
Cancel
Save