Improve -rpartial, -juxt, and -compose

* dash.el (-rpartial, -juxt): Mark as pure and side-effect-free.
Fix docstrings.
(-compose): Ditto.  Optimize for speed.
* dev/examples.el (-rpartial, -juxt, -compose): Extend tests.

* README.md:
* dash.texi: Regenerate docs.
master
Basil L. Contovounesios 5 years ago
parent 1ca9d6b9b2
commit 5326ed8c9f
No known key found for this signature in database
GPG Key ID: 205AB54A5D5D8CFF
  1. 44
      README.md
  2. 42
      dash.el
  3. 60
      dash.texi
  4. 45
      dev/examples.el

@ -2811,40 +2811,44 @@ was called.
#### -rpartial `(fn &rest args)`
Takes a function `fn` and fewer than the normal arguments to `fn`,
and returns a fn that takes a variable number of additional `args`.
When called, the returned function calls `fn` with the additional
args first and then `args`.
Return a function that is a partial application of `fn` to `args`.
`args` is a list of the last `n` arguments to pass to `fn`. The result
is a new function which does the same as `fn`, except that the last
`n` arguments are fixed at the values with which this function was
called. This is like [`-partial`](#-partial-fun-rest-args), except the arguments are fixed
starting from the right rather than the left.
```el
(funcall (-rpartial '- 5) 8) ;; => 3
(funcall (-rpartial '- 5 2) 10) ;; => 3
(funcall (-rpartial #'- 5)) ;; => -5
(funcall (-rpartial #'- 5) 8) ;; => 3
(funcall (-rpartial #'- 5 2) 10) ;; => 3
```
#### -juxt `(&rest fns)`
Takes a list of functions and returns a fn that is the
juxtaposition of those fns. The returned fn takes a variable
number of args, and returns a list containing the result of
applying each fn to the args (left-to-right).
Return a function that is the juxtaposition of `fns`.
The returned function takes a variable number of `args`, applies
each of `fns` in turn to `args`, and returns the list of results.
```el
(funcall (-juxt '+ '-) 3 5) ;; => (8 -2)
(-map (-juxt 'identity 'square) '(1 2 3)) ;; => ((1 1) (2 4) (3 9))
(funcall (-juxt) 1 2) ;; => ()
(funcall (-juxt #'+ #'- #'* #'/) 7 5) ;; => (12 2 35 1)
(mapcar (-juxt #'number-to-string #'1+) '(1 2)) ;; => (("1" 2) ("2" 3))
```
#### -compose `(&rest fns)`
Takes a list of functions and returns a fn that is the
composition of those fns. The returned fn takes a variable
number of arguments, and returns the result of applying
each fn to the result of applying the previous fn to
the arguments (right-to-left).
Compose `fns` into a single composite function.
Return a function that takes a variable number of `args`, applies
the last function in `fns` to `args`, and returns the result of
calling each remaining function on the result of the previous
function, right-to-left. If no `fns` are given, return a variadic
`identity` function.
```el
(funcall (-compose 'square '+) 2 3) ;; => (square (+ 2 3))
(funcall (-compose 'identity 'square) 3) ;; => (square 3)
(funcall (-compose 'square 'identity) 3) ;; => (square 3)
(funcall (-compose #'- #'1+ #'+) 1 2 3) ;; => -7
(funcall (-compose #'identity #'1+) 3) ;; => 4
(mapcar (-compose #'not #'stringp) '(nil "")) ;; => (t nil)
```
#### -applify `(fn)`

@ -3002,28 +3002,38 @@ structure such as plist or alist."
(defalias '-partial #'apply-partially)
(defun -rpartial (fn &rest args)
"Takes a function FN and fewer than the normal arguments to FN,
and returns a fn that takes a variable number of additional ARGS.
When called, the returned function calls FN with the additional
args first and then ARGS."
"Return a function that is a partial application of FN to ARGS.
ARGS is a list of the last N arguments to pass to FN. The result
is a new function which does the same as FN, except that the last
N arguments are fixed at the values with which this function was
called. This is like `-partial', except the arguments are fixed
starting from the right rather than the left."
(declare (pure t) (side-effect-free t))
(lambda (&rest args-before) (apply fn (append args-before args))))
(defun -juxt (&rest fns)
"Takes a list of functions and returns a fn that is the
juxtaposition of those fns. The returned fn takes a variable
number of args, and returns a list containing the result of
applying each fn to the args (left-to-right)."
"Return a function that is the juxtaposition of FNS.
The returned function takes a variable number of ARGS, applies
each of FNS in turn to ARGS, and returns the list of results."
(declare (pure t) (side-effect-free t))
(lambda (&rest args) (mapcar (lambda (x) (apply x args)) fns)))
(defun -compose (&rest fns)
"Takes a list of functions and returns a fn that is the
composition of those fns. The returned fn takes a variable
number of arguments, and returns the result of applying
each fn to the result of applying the previous fn to
the arguments (right-to-left)."
(lambda (&rest args)
(car (-reduce-r-from (lambda (fn xs) (list (apply fn xs)))
args fns))))
"Compose FNS into a single composite function.
Return a function that takes a variable number of ARGS, applies
the last function in FNS to ARGS, and returns the result of
calling each remaining function on the result of the previous
function, right-to-left. If no FNS are given, return a variadic
`identity' function."
(declare (pure t) (side-effect-free t))
(let* ((fns (nreverse fns))
(head (car fns))
(tail (cdr fns)))
(cond (tail
(lambda (&rest args)
(--reduce-from (funcall it acc) (apply head args) tail)))
(fns head)
((lambda (&optional arg &rest _) arg)))))
(defun -applify (fn)
"Return a function that applies FN to a single list of args.

@ -4226,18 +4226,24 @@ was called.
@anchor{-rpartial}
@defun -rpartial (fn &rest args)
Takes a function @var{fn} and fewer than the normal arguments to @var{fn},
and returns a fn that takes a variable number of additional @var{args}.
When called, the returned function calls @var{fn} with the additional
args first and then @var{args}.
Return a function that is a partial application of @var{fn} to @var{args}.
@var{args} is a list of the last @var{n} arguments to pass to @var{fn}. The result
is a new function which does the same as @var{fn}, except that the last
@var{n} arguments are fixed at the values with which this function was
called. This is like @code{-partial} (@pxref{-partial}), except the arguments are fixed
starting from the right rather than the left.
@example
@group
(funcall (-rpartial '- 5) 8)
(funcall (-rpartial #'- 5))
@result{} -5
@end group
@group
(funcall (-rpartial #'- 5) 8)
@result{} 3
@end group
@group
(funcall (-rpartial '- 5 2) 10)
(funcall (-rpartial #'- 5 2) 10)
@result{} 3
@end group
@end example
@ -4245,43 +4251,47 @@ args first and then @var{args}.
@anchor{-juxt}
@defun -juxt (&rest fns)
Takes a list of functions and returns a fn that is the
juxtaposition of those fns. The returned fn takes a variable
number of args, and returns a list containing the result of
applying each fn to the args (left-to-right).
Return a function that is the juxtaposition of @var{fns}.
The returned function takes a variable number of @var{args}, applies
each of @var{fns} in turn to @var{args}, and returns the list of results.
@example
@group
(funcall (-juxt '+ '-) 3 5)
@result{} (8 -2)
(funcall (-juxt) 1 2)
@result{} ()
@end group
@group
(funcall (-juxt #'+ #'- #'* #'/) 7 5)
@result{} (12 2 35 1)
@end group
@group
(-map (-juxt 'identity 'square) '(1 2 3))
@result{} ((1 1) (2 4) (3 9))
(mapcar (-juxt #'number-to-string #'1+) '(1 2))
@result{} (("1" 2) ("2" 3))
@end group
@end example
@end defun
@anchor{-compose}
@defun -compose (&rest fns)
Takes a list of functions and returns a fn that is the
composition of those fns. The returned fn takes a variable
number of arguments, and returns the result of applying
each fn to the result of applying the previous fn to
the arguments (right-to-left).
Compose @var{fns} into a single composite function.
Return a function that takes a variable number of @var{args}, applies
the last function in @var{fns} to @var{args}, and returns the result of
calling each remaining function on the result of the previous
function, right-to-left. If no @var{fns} are given, return a variadic
@code{identity} function.
@example
@group
(funcall (-compose 'square '+) 2 3)
@result{} (square (+ 2 3))
(funcall (-compose #'- #'1+ #'+) 1 2 3)
@result{} -7
@end group
@group
(funcall (-compose 'identity 'square) 3)
@result{} (square 3)
(funcall (-compose #'identity #'1+) 3)
@result{} 4
@end group
@group
(funcall (-compose 'square 'identity) 3)
@result{} (square 3)
(mapcar (-compose #'not #'stringp) '(nil ""))
@result{} (t nil)
@end group
@end example
@end defun

@ -1640,20 +1640,37 @@ or readability."
(funcall (-partial #'+) 5) => 5
(apply (-partial #'+ 5) 10 '(1 2)) => 18)
(unless (version< emacs-version "24")
(defexamples -rpartial
(funcall (-rpartial '- 5) 8) => 3
(funcall (-rpartial '- 5 2) 10) => 3)
(defexamples -juxt
(funcall (-juxt '+ '-) 3 5) => '(8 -2)
(-map (-juxt 'identity 'square) '(1 2 3)) => '((1 1) (2 4) (3 9)))
(defexamples -compose
(funcall (-compose 'square '+) 2 3) => (square (+ 2 3))
(funcall (-compose 'identity 'square) 3) => (square 3)
(funcall (-compose 'square 'identity) 3) => (square 3)
(funcall (-compose (-compose 'not 'even?) 'square) 3) => (funcall (-compose 'not (-compose 'even? 'square)) 3)))
(defexamples -rpartial
(funcall (-rpartial #'- 5)) => -5
(funcall (-rpartial #'- 5) 8) => 3
(funcall (-rpartial #'- 5 2) 10) => 3
(funcall (-rpartial #'-)) => 0
(apply (-rpartial #'- 1) 2 '(20 3)) => -22)
(defexamples -juxt
(funcall (-juxt) 1 2) => '()
(funcall (-juxt #'+ #'- #'* #'/) 7 5) => '(12 2 35 1)
(mapcar (-juxt #'number-to-string #'1+) '(1 2)) => '(("1" 2) ("2" 3))
(funcall (-juxt #'+ #'-)) => '(0 0)
(funcall (-juxt)) => '())
(defexamples -compose
(funcall (-compose #'- #'1+ #'+) 1 2 3) => -7
(funcall (-compose #'identity #'1+) 3) => 4
(mapcar (-compose #'not #'stringp) '(nil "")) => '(t nil)
(funcall (-compose #'1+ #'identity) 3) => 4
(mapcar (lambda (fn)
(list (funcall fn 0) (funcall fn 1)))
(list (-compose (-compose #'natnump #'1+) #'lognot)
(-compose #'natnump (-compose #'1+ #'lognot))
(-compose #'natnump #'1+ #'lognot)))
=> '((t nil) (t nil) (t nil))
(funcall (-compose)) => nil
(funcall (-compose) nil) => nil
(funcall (-compose) nil 1) => nil
(funcall (-compose) 1) => 1
(funcall (-compose) 1 2) => 1
(-compose #'+) => #'+)
(defexamples -applify
(funcall (-applify #'+) ()) => 0

Loading…
Cancel
Save