|
|
This is dash.info, produced by makeinfo version 6.7 from dash.texi. |
|
|
|
|
|
This manual is for Dash version 2.19.1. |
|
|
|
|
|
Copyright © 2012–2021 Free Software Foundation, Inc. |
|
|
|
|
|
Permission is granted to copy, distribute and/or modify this |
|
|
document under the terms of the GNU Free Documentation License, |
|
|
Version 1.3 or any later version published by the Free Software |
|
|
Foundation; with the Invariant Sections being “GNU General Public |
|
|
License,” and no Front-Cover Texts or Back-Cover Texts. A copy of |
|
|
the license is included in the section entitled “GNU Free |
|
|
Documentation License”. |
|
|
INFO-DIR-SECTION Emacs |
|
|
START-INFO-DIR-ENTRY |
|
|
* Dash: (dash.info). A modern list library for GNU Emacs. |
|
|
END-INFO-DIR-ENTRY |
|
|
|
|
|
|
|
|
File: dash.info, Node: Top, Next: Installation, Up: (dir) |
|
|
|
|
|
Dash |
|
|
**** |
|
|
|
|
|
This manual is for Dash version 2.19.1. |
|
|
|
|
|
Copyright © 2012–2021 Free Software Foundation, Inc. |
|
|
|
|
|
Permission is granted to copy, distribute and/or modify this |
|
|
document under the terms of the GNU Free Documentation License, |
|
|
Version 1.3 or any later version published by the Free Software |
|
|
Foundation; with the Invariant Sections being “GNU General Public |
|
|
License,” and no Front-Cover Texts or Back-Cover Texts. A copy of |
|
|
the license is included in the section entitled “GNU Free |
|
|
Documentation License”. |
|
|
|
|
|
* Menu: |
|
|
|
|
|
* Installation:: Installing and configuring Dash. |
|
|
* Functions:: Dash API reference. |
|
|
* Development:: Contributing to Dash development. |
|
|
|
|
|
Appendices |
|
|
|
|
|
* FDL:: The license for this documentation. |
|
|
* GPL:: Conditions for copying and changing Dash. |
|
|
* Index:: Index including functions and macros. |
|
|
|
|
|
— The Detailed Node Listing — |
|
|
|
|
|
Installation |
|
|
|
|
|
* Using in a package:: Listing Dash as a package dependency. |
|
|
* Fontification of special variables:: Font Lock of anaphoric macro variables. |
|
|
* Info symbol lookup:: Looking up Dash symbols in this manual. |
|
|
|
|
|
Functions |
|
|
|
|
|
* Maps:: |
|
|
* Sublist selection:: |
|
|
* List to list:: |
|
|
* Reductions:: |
|
|
* Unfolding:: |
|
|
* Predicates:: |
|
|
* Partitioning:: |
|
|
* Indexing:: |
|
|
* Set operations:: |
|
|
* Other list operations:: |
|
|
* Tree operations:: |
|
|
* Threading macros:: |
|
|
* Binding:: |
|
|
* Side effects:: |
|
|
* Destructive operations:: |
|
|
* Function combinators:: |
|
|
|
|
|
Development |
|
|
|
|
|
* Contribute:: How to contribute. |
|
|
* Contributors:: List of contributors. |
|
|
|
|
|
|
|
|
File: dash.info, Node: Installation, Next: Functions, Prev: Top, Up: Top |
|
|
|
|
|
1 Installation |
|
|
************** |
|
|
|
|
|
Dash is available on GNU ELPA (https://elpa.gnu.org/), GNU-devel ELPA |
|
|
(https://elpa.gnu.org/devel/), and MELPA (https://melpa.org/), and can |
|
|
be installed with the standard command ‘package-install’ (*note |
|
|
(emacs)Package Installation::). |
|
|
|
|
|
‘M-x package-install <RET> dash <RET>’ |
|
|
Install the Dash library. |
|
|
|
|
|
Alternatively, you can just dump ‘dash.el’ in your ‘load-path’ |
|
|
somewhere (*note (emacs)Lisp Libraries::). |
|
|
|
|
|
* Menu: |
|
|
|
|
|
* Using in a package:: Listing Dash as a package dependency. |
|
|
* Fontification of special variables:: Font Lock of anaphoric macro variables. |
|
|
* Info symbol lookup:: Looking up Dash symbols in this manual. |
|
|
|
|
|
|
|
|
File: dash.info, Node: Using in a package, Next: Fontification of special variables, Up: Installation |
|
|
|
|
|
1.1 Using in a package |
|
|
====================== |
|
|
|
|
|
If you use Dash in your own package, be sure to list it as a dependency |
|
|
in the library’s headers as follows (*note (elisp)Library Headers::). |
|
|
|
|
|
;; Package-Requires: ((dash "2.19.1")) |
|
|
|
|
|
|
|
|
File: dash.info, Node: Fontification of special variables, Next: Info symbol lookup, Prev: Using in a package, Up: Installation |
|
|
|
|
|
1.2 Fontification of special variables |
|
|
====================================== |
|
|
|
|
|
The autoloaded minor mode ‘dash-fontify-mode’ is provided for optional |
|
|
fontification of anaphoric Dash variables (‘it’, ‘acc’, etc.) in Emacs |
|
|
Lisp buffers using search-based Font Lock (*note (emacs)Font Lock::). |
|
|
In older Emacs versions which do not dynamically detect macros, the |
|
|
minor mode also fontifies calls to Dash macros. |
|
|
|
|
|
To automatically enable the minor mode in all Emacs Lisp buffers, |
|
|
just call its autoloaded global counterpart ‘global-dash-fontify-mode’, |
|
|
either interactively or from your ‘user-init-file’: |
|
|
|
|
|
(global-dash-fontify-mode) |
|
|
|
|
|
|
|
|
File: dash.info, Node: Info symbol lookup, Prev: Fontification of special variables, Up: Installation |
|
|
|
|
|
1.3 Info symbol lookup |
|
|
====================== |
|
|
|
|
|
While editing Elisp files, you can use ‘C-h S’ (‘info-lookup-symbol’) to |
|
|
look up Elisp symbols in the relevant Info manuals (*note (emacs)Info |
|
|
Lookup::). To enable the same for Dash symbols, use the command |
|
|
‘dash-register-info-lookup’. It can be called directly when needed, or |
|
|
automatically from your ‘user-init-file’. For example: |
|
|
|
|
|
(with-eval-after-load 'info-look |
|
|
(dash-register-info-lookup)) |
|
|
|
|
|
|
|
|
File: dash.info, Node: Functions, Next: Development, Prev: Installation, Up: Top |
|
|
|
|
|
2 Functions |
|
|
*********** |
|
|
|
|
|
This chapter contains reference documentation for the Dash API |
|
|
(Application Programming Interface). The names of all public functions |
|
|
defined in the library are prefixed with a dash character (‘-’). |
|
|
|
|
|
The library also provides anaphoric macro versions of functions where |
|
|
that makes sense. The names of these macros are prefixed with two |
|
|
dashes (‘--’) instead of one. |
|
|
|
|
|
For instance, while the function ‘-map’ applies a function to each |
|
|
element of a list, its anaphoric counterpart ‘--map’ evaluates a form |
|
|
with the local variable ‘it’ temporarily bound to the current list |
|
|
element instead. |
|
|
|
|
|
;; Normal version. |
|
|
(-map (lambda (n) (* n n)) '(1 2 3 4)) |
|
|
⇒ (1 4 9 16) |
|
|
|
|
|
;; Anaphoric version. |
|
|
(--map (* it it) '(1 2 3 4)) |
|
|
⇒ (1 4 9 16) |
|
|
|
|
|
The normal version can, of course, also be written as in the |
|
|
following example, which demonstrates the utility of both versions. |
|
|
|
|
|
(defun my-square (n) |
|
|
"Return N multiplied by itself." |
|
|
(* n n)) |
|
|
|
|
|
(-map #'my-square '(1 2 3 4)) |
|
|
⇒ (1 4 9 16) |
|
|
|
|
|
* Menu: |
|
|
|
|
|
* Maps:: |
|
|
* Sublist selection:: |
|
|
* List to list:: |
|
|
* Reductions:: |
|
|
* Unfolding:: |
|
|
* Predicates:: |
|
|
* Partitioning:: |
|
|
* Indexing:: |
|
|
* Set operations:: |
|
|
* Other list operations:: |
|
|
* Tree operations:: |
|
|
* Threading macros:: |
|
|
* Binding:: |
|
|
* Side effects:: |
|
|
* Destructive operations:: |
|
|
* Function combinators:: |
|
|
|
|
|
|
|
|
File: dash.info, Node: Maps, Next: Sublist selection, Up: Functions |
|
|
|
|
|
2.1 Maps |
|
|
======== |
|
|
|
|
|
Functions in this category take a transforming function, which is then |
|
|
applied sequentially to each or selected elements of the input list. |
|
|
The results are collected in order and returned as a new list. |
|
|
|
|
|
-- Function: -map (fn list) |
|
|
Apply FN to each item in LIST and return the list of results. |
|
|
|
|
|
This function’s anaphoric counterpart is ‘--map’. |
|
|
|
|
|
(-map (lambda (num) (* num num)) '(1 2 3 4)) |
|
|
⇒ (1 4 9 16) |
|
|
(-map #'1+ '(1 2 3 4)) |
|
|
⇒ (2 3 4 5) |
|
|
(--map (* it it) '(1 2 3 4)) |
|
|
⇒ (1 4 9 16) |
|
|
|
|
|
-- Function: -map-when (pred rep list) |
|
|
Use PRED to conditionally apply REP to each item in LIST. Return a |
|
|
copy of LIST where the items for which PRED returns ‘nil’ are |
|
|
unchanged, and the rest are mapped through the REP function. |
|
|
|
|
|
Alias: ‘-replace-where’ |
|
|
|
|
|
See also: ‘-update-at’ (*note -update-at::) |
|
|
|
|
|
(-map-when 'even? 'square '(1 2 3 4)) |
|
|
⇒ (1 4 3 16) |
|
|
(--map-when (> it 2) (* it it) '(1 2 3 4)) |
|
|
⇒ (1 2 9 16) |
|
|
(--map-when (= it 2) 17 '(1 2 3 4)) |
|
|
⇒ (1 17 3 4) |
|
|
|
|
|
-- Function: -map-first (pred rep list) |
|
|
Use PRED to determine the first item in LIST to call REP on. |
|
|
Return a copy of LIST where the first item for which PRED returns |
|
|
non-‘nil’ is replaced with the result of calling REP on that item. |
|
|
|
|
|
See also: ‘-map-when’ (*note -map-when::), ‘-replace-first’ (*note |
|
|
-replace-first::) |
|
|
|
|
|
(-map-first 'even? 'square '(1 2 3 4)) |
|
|
⇒ (1 4 3 4) |
|
|
(--map-first (> it 2) (* it it) '(1 2 3 4)) |
|
|
⇒ (1 2 9 4) |
|
|
(--map-first (= it 2) 17 '(1 2 3 2)) |
|
|
⇒ (1 17 3 2) |
|
|
|
|
|
-- Function: -map-last (pred rep list) |
|
|
Use PRED to determine the last item in LIST to call REP on. Return |
|
|
a copy of LIST where the last item for which PRED returns non-‘nil’ |
|
|
is replaced with the result of calling REP on that item. |
|
|
|
|
|
See also: ‘-map-when’ (*note -map-when::), ‘-replace-last’ (*note |
|
|
-replace-last::) |
|
|
|
|
|
(-map-last 'even? 'square '(1 2 3 4)) |
|
|
⇒ (1 2 3 16) |
|
|
(--map-last (> it 2) (* it it) '(1 2 3 4)) |
|
|
⇒ (1 2 3 16) |
|
|
(--map-last (= it 2) 17 '(1 2 3 2)) |
|
|
⇒ (1 2 3 17) |
|
|
|
|
|
-- Function: -map-indexed (fn list) |
|
|
Apply FN to each index and item in LIST and return the list of |
|
|
results. This is like ‘-map’ (*note -map::), but FN takes two |
|
|
arguments: the index of the current element within LIST, and the |
|
|
element itself. |
|
|
|
|
|
This function’s anaphoric counterpart is ‘--map-indexed’. |
|
|
|
|
|
For a side-effecting variant, see also ‘-each-indexed’ (*note |
|
|
-each-indexed::). |
|
|
|
|
|
(-map-indexed (lambda (index item) (- item index)) '(1 2 3 4)) |
|
|
⇒ (1 1 1 1) |
|
|
(--map-indexed (- it it-index) '(1 2 3 4)) |
|
|
⇒ (1 1 1 1) |
|
|
(-map-indexed #'* '(1 2 3 4)) |
|
|
⇒ (0 2 6 12) |
|
|
|
|
|
-- Function: -annotate (fn list) |
|
|
Return a list of cons cells where each cell is FN applied to each |
|
|
element of LIST paired with the unmodified element of LIST. |
|
|
|
|
|
(-annotate '1+ '(1 2 3)) |
|
|
⇒ ((2 . 1) (3 . 2) (4 . 3)) |
|
|
(-annotate 'length '(("h" "e" "l" "l" "o") ("hello" "world"))) |
|
|
⇒ ((5 "h" "e" "l" "l" "o") (2 "hello" "world")) |
|
|
(--annotate (< 1 it) '(0 1 2 3)) |
|
|
⇒ ((nil . 0) (nil . 1) (t . 2) (t . 3)) |
|
|
|
|
|
-- Function: -splice (pred fun list) |
|
|
Splice lists generated by FUN in place of elements matching PRED in |
|
|
LIST. |
|
|
|
|
|
FUN takes the element matching PRED as input. |
|
|
|
|
|
This function can be used as replacement for ‘,@’ in case you need |
|
|
to splice several lists at marked positions (for example with |
|
|
keywords). |
|
|
|
|
|
See also: ‘-splice-list’ (*note -splice-list::), ‘-insert-at’ |
|
|
(*note -insert-at::) |
|
|
|
|
|
(-splice 'even? (lambda (x) (list x x)) '(1 2 3 4)) |
|
|
⇒ (1 2 2 3 4 4) |
|
|
(--splice 't (list it it) '(1 2 3 4)) |
|
|
⇒ (1 1 2 2 3 3 4 4) |
|
|
(--splice (equal it :magic) '((list of) (magical) (code)) '((foo) (bar) :magic (baz))) |
|
|
⇒ ((foo) (bar) (list of) (magical) (code) (baz)) |
|
|
|
|
|
-- Function: -splice-list (pred new-list list) |
|
|
Splice NEW-LIST in place of elements matching PRED in LIST. |
|
|
|
|
|
See also: ‘-splice’ (*note -splice::), ‘-insert-at’ (*note |
|
|
-insert-at::) |
|
|
|
|
|
(-splice-list 'keywordp '(a b c) '(1 :foo 2)) |
|
|
⇒ (1 a b c 2) |
|
|
(-splice-list 'keywordp nil '(1 :foo 2)) |
|
|
⇒ (1 2) |
|
|
(--splice-list (keywordp it) '(a b c) '(1 :foo 2)) |
|
|
⇒ (1 a b c 2) |
|
|
|
|
|
-- Function: -mapcat (fn list) |
|
|
Return the concatenation of the result of mapping FN over LIST. |
|
|
Thus function FN should return a list. |
|
|
|
|
|
(-mapcat 'list '(1 2 3)) |
|
|
⇒ (1 2 3) |
|
|
(-mapcat (lambda (item) (list 0 item)) '(1 2 3)) |
|
|
⇒ (0 1 0 2 0 3) |
|
|
(--mapcat (list 0 it) '(1 2 3)) |
|
|
⇒ (0 1 0 2 0 3) |
|
|
|
|
|
-- Function: -copy (list) |
|
|
Create a shallow copy of LIST. |
|
|
|
|
|
(-copy '(1 2 3)) |
|
|
⇒ (1 2 3) |
|
|
(let ((a '(1 2 3))) (eq a (-copy a))) |
|
|
⇒ nil |
|
|
|
|
|
|
|
|
File: dash.info, Node: Sublist selection, Next: List to list, Prev: Maps, Up: Functions |
|
|
|
|
|
2.2 Sublist selection |
|
|
===================== |
|
|
|
|
|
Functions returning a sublist of the original list. |
|
|
|
|
|
-- Function: -filter (pred list) |
|
|
Return a new list of the items in LIST for which PRED returns |
|
|
non-‘nil’. |
|
|
|
|
|
Alias: ‘-select’. |
|
|
|
|
|
This function’s anaphoric counterpart is ‘--filter’. |
|
|
|
|
|
For similar operations, see also ‘-keep’ (*note -keep::) and |
|
|
‘-remove’ (*note -remove::). |
|
|
|
|
|
(-filter (lambda (num) (= 0 (% num 2))) '(1 2 3 4)) |
|
|
⇒ (2 4) |
|
|
(-filter #'natnump '(-2 -1 0 1 2)) |
|
|
⇒ (0 1 2) |
|
|
(--filter (= 0 (% it 2)) '(1 2 3 4)) |
|
|
⇒ (2 4) |
|
|
|
|
|
-- Function: -remove (pred list) |
|
|
Return a new list of the items in LIST for which PRED returns |
|
|
‘nil’. |
|
|
|
|
|
Alias: ‘-reject’. |
|
|
|
|
|
This function’s anaphoric counterpart is ‘--remove’. |
|
|
|
|
|
For similar operations, see also ‘-keep’ (*note -keep::) and |
|
|
‘-filter’ (*note -filter::). |
|
|
|
|
|
(-remove (lambda (num) (= 0 (% num 2))) '(1 2 3 4)) |
|
|
⇒ (1 3) |
|
|
(-remove #'natnump '(-2 -1 0 1 2)) |
|
|
⇒ (-2 -1) |
|
|
(--remove (= 0 (% it 2)) '(1 2 3 4)) |
|
|
⇒ (1 3) |
|
|
|
|
|
-- Function: -remove-first (pred list) |
|
|
Remove the first item from LIST for which PRED returns non-‘nil’. |
|
|
This is a non-destructive operation, but only the front of LIST |
|
|
leading up to the removed item is a copy; the rest is LIST’s |
|
|
original tail. If no item is removed, then the result is a |
|
|
complete copy. |
|
|
|
|
|
Alias: ‘-reject-first’. |
|
|
|
|
|
This function’s anaphoric counterpart is ‘--remove-first’. |
|
|
|
|
|
See also ‘-map-first’ (*note -map-first::), ‘-remove-item’ (*note |
|
|
-remove-item::), and ‘-remove-last’ (*note -remove-last::). |
|
|
|
|
|
(-remove-first #'natnump '(-2 -1 0 1 2)) |
|
|
⇒ (-2 -1 1 2) |
|
|
(-remove-first #'stringp '(1 2 "first" "second")) |
|
|
⇒ (1 2 "second") |
|
|
(--remove-first (> it 3) '(1 2 3 4 5 6)) |
|
|
⇒ (1 2 3 5 6) |
|
|
|
|
|
-- Function: -remove-last (pred list) |
|
|
Remove the last item from LIST for which PRED returns non-‘nil’. |
|
|
The result is a copy of LIST regardless of whether an element is |
|
|
removed. |
|
|
|
|
|
Alias: ‘-reject-last’. |
|
|
|
|
|
This function’s anaphoric counterpart is ‘--remove-last’. |
|
|
|
|
|
See also ‘-map-last’ (*note -map-last::), ‘-remove-item’ (*note |
|
|
-remove-item::), and ‘-remove-first’ (*note -remove-first::). |
|
|
|
|
|
(-remove-last #'natnump '(1 3 5 4 7 8 10 -11)) |
|
|
⇒ (1 3 5 4 7 8 -11) |
|
|
(-remove-last #'stringp '(1 2 "last" "second")) |
|
|
⇒ (1 2 "last") |
|
|
(--remove-last (> it 3) '(1 2 3 4 5 6 7 8 9 10)) |
|
|
⇒ (1 2 3 4 5 6 7 8 9) |
|
|
|
|
|
-- Function: -remove-item (item list) |
|
|
Return a copy of LIST with all occurrences of ITEM removed. The |
|
|
comparison is done with ‘equal’. |
|
|
|
|
|
(-remove-item 3 '(1 2 3 2 3 4 5 3)) |
|
|
⇒ (1 2 2 4 5) |
|
|
(-remove-item 'foo '(foo bar baz foo)) |
|
|
⇒ (bar baz) |
|
|
(-remove-item "bob" '("alice" "bob" "eve" "bob")) |
|
|
⇒ ("alice" "eve") |
|
|
|
|
|
-- Function: -non-nil (list) |
|
|
Return a copy of LIST with all ‘nil’ items removed. |
|
|
|
|
|
(-non-nil '(nil 1 nil 2 nil nil 3 4 nil 5 nil)) |
|
|
⇒ (1 2 3 4 5) |
|
|
(-non-nil '((nil))) |
|
|
⇒ ((nil)) |
|
|
(-non-nil ()) |
|
|
⇒ () |
|
|
|
|
|
-- Function: -slice (list from &optional to step) |
|
|
Return copy of LIST, starting from index FROM to index TO. |
|
|
|
|
|
FROM or TO may be negative. These values are then interpreted |
|
|
modulo the length of the list. |
|
|
|
|
|
If STEP is a number, only each STEPth item in the resulting section |
|
|
is returned. Defaults to 1. |
|
|
|
|
|
(-slice '(1 2 3 4 5) 1) |
|
|
⇒ (2 3 4 5) |
|
|
(-slice '(1 2 3 4 5) 0 3) |
|
|
⇒ (1 2 3) |
|
|
(-slice '(1 2 3 4 5 6 7 8 9) 1 -1 2) |
|
|
⇒ (2 4 6 8) |
|
|
|
|
|
-- Function: -take (n list) |
|
|
Return a copy of the first N items in LIST. Return a copy of LIST |
|
|
if it contains N items or fewer. Return ‘nil’ if N is zero or |
|
|
less. |
|
|
|
|
|
See also: ‘-take-last’ (*note -take-last::). |
|
|
|
|
|
(-take 3 '(1 2 3 4 5)) |
|
|
⇒ (1 2 3) |
|
|
(-take 17 '(1 2 3 4 5)) |
|
|
⇒ (1 2 3 4 5) |
|
|
(-take 0 '(1 2 3 4 5)) |
|
|
⇒ () |
|
|
|
|
|
-- Function: -take-last (n list) |
|
|
Return a copy of the last N items of LIST in order. Return a copy |
|
|
of LIST if it contains N items or fewer. Return ‘nil’ if N is zero |
|
|
or less. |
|
|
|
|
|
See also: ‘-take’ (*note -take::). |
|
|
|
|
|
(-take-last 3 '(1 2 3 4 5)) |
|
|
⇒ (3 4 5) |
|
|
(-take-last 17 '(1 2 3 4 5)) |
|
|
⇒ (1 2 3 4 5) |
|
|
(-take-last 1 '(1 2 3 4 5)) |
|
|
⇒ (5) |
|
|
|
|
|
-- Function: -drop (n list) |
|
|
Return the tail (not a copy) of LIST without the first N items. |
|
|
Return ‘nil’ if LIST contains N items or fewer. Return LIST if N |
|
|
is zero or less. |
|
|
|
|
|
For another variant, see also ‘-drop-last’ (*note -drop-last::). |
|
|
|
|
|
(-drop 3 '(1 2 3 4 5)) |
|
|
⇒ (4 5) |
|
|
(-drop 17 '(1 2 3 4 5)) |
|
|
⇒ () |
|
|
(-drop 0 '(1 2 3 4 5)) |
|
|
⇒ (1 2 3 4 5) |
|
|
|
|
|
-- Function: -drop-last (n list) |
|
|
Return a copy of LIST without its last N items. Return a copy of |
|
|
LIST if N is zero or less. Return ‘nil’ if LIST contains N items |
|
|
or fewer. |
|
|
|
|
|
See also: ‘-drop’ (*note -drop::). |
|
|
|
|
|
(-drop-last 3 '(1 2 3 4 5)) |
|
|
⇒ (1 2) |
|
|
(-drop-last 17 '(1 2 3 4 5)) |
|
|
⇒ () |
|
|
(-drop-last 0 '(1 2 3 4 5)) |
|
|
⇒ (1 2 3 4 5) |
|
|
|
|
|
-- Function: -take-while (pred list) |
|
|
Take successive items from LIST for which PRED returns non-‘nil’. |
|
|
PRED is a function of one argument. Return a new list of the |
|
|
successive elements from the start of LIST for which PRED returns |
|
|
non-‘nil’. |
|
|
|
|
|
This function’s anaphoric counterpart is ‘--take-while’. |
|
|
|
|
|
For another variant, see also ‘-drop-while’ (*note -drop-while::). |
|
|
|
|
|
(-take-while #'even? '(1 2 3 4)) |
|
|
⇒ () |
|
|
(-take-while #'even? '(2 4 5 6)) |
|
|
⇒ (2 4) |
|
|
(--take-while (< it 4) '(1 2 3 4 3 2 1)) |
|
|
⇒ (1 2 3) |
|
|
|
|
|
-- Function: -drop-while (pred list) |
|
|
Drop successive items from LIST for which PRED returns non-‘nil’. |
|
|
PRED is a function of one argument. Return the tail (not a copy) |
|
|
of LIST starting from its first element for which PRED returns |
|
|
‘nil’. |
|
|
|
|
|
This function’s anaphoric counterpart is ‘--drop-while’. |
|
|
|
|
|
For another variant, see also ‘-take-while’ (*note -take-while::). |
|
|
|
|
|
(-drop-while #'even? '(1 2 3 4)) |
|
|
⇒ (1 2 3 4) |
|
|
(-drop-while #'even? '(2 4 5 6)) |
|
|
⇒ (5 6) |
|
|
(--drop-while (< it 4) '(1 2 3 4 3 2 1)) |
|
|
⇒ (4 3 2 1) |
|
|
|
|
|
-- Function: -select-by-indices (indices list) |
|
|
Return a list whose elements are elements from LIST selected as |
|
|
‘(nth i list)‘ for all i from INDICES. |
|
|
|
|
|
(-select-by-indices '(4 10 2 3 6) '("v" "e" "l" "o" "c" "i" "r" "a" "p" "t" "o" "r")) |
|
|
⇒ ("c" "o" "l" "o" "r") |
|
|
(-select-by-indices '(2 1 0) '("a" "b" "c")) |
|
|
⇒ ("c" "b" "a") |
|
|
(-select-by-indices '(0 1 2 0 1 3 3 1) '("f" "a" "r" "l")) |
|
|
⇒ ("f" "a" "r" "f" "a" "l" "l" "a") |
|
|
|
|
|
-- Function: -select-columns (columns table) |
|
|
Select COLUMNS from TABLE. |
|
|
|
|
|
TABLE is a list of lists where each element represents one row. It |
|
|
is assumed each row has the same length. |
|
|
|
|
|
Each row is transformed such that only the specified COLUMNS are |
|
|
selected. |
|
|
|
|
|
See also: ‘-select-column’ (*note -select-column::), |
|
|
‘-select-by-indices’ (*note -select-by-indices::) |
|
|
|
|
|
(-select-columns '(0 2) '((1 2 3) (a b c) (:a :b :c))) |
|
|
⇒ ((1 3) (a c) (:a :c)) |
|
|
(-select-columns '(1) '((1 2 3) (a b c) (:a :b :c))) |
|
|
⇒ ((2) (b) (:b)) |
|
|
(-select-columns nil '((1 2 3) (a b c) (:a :b :c))) |
|
|
⇒ (nil nil nil) |
|
|
|
|
|
-- Function: -select-column (column table) |
|
|
Select COLUMN from TABLE. |
|
|
|
|
|
TABLE is a list of lists where each element represents one row. It |
|
|
is assumed each row has the same length. |
|
|
|
|
|
The single selected column is returned as a list. |
|
|
|
|
|
See also: ‘-select-columns’ (*note -select-columns::), |
|
|
‘-select-by-indices’ (*note -select-by-indices::) |
|
|
|
|
|
(-select-column 1 '((1 2 3) (a b c) (:a :b :c))) |
|
|
⇒ (2 b :b) |
|
|
|
|
|
|
|
|
File: dash.info, Node: List to list, Next: Reductions, Prev: Sublist selection, Up: Functions |
|
|
|
|
|
2.3 List to list |
|
|
================ |
|
|
|
|
|
Functions returning a modified copy of the input list. |
|
|
|
|
|
-- Function: -keep (fn list) |
|
|
Return a new list of the non-‘nil’ results of applying FN to each |
|
|
item in LIST. Like ‘-filter’ (*note -filter::), but returns the |
|
|
non-‘nil’ results of FN instead of the corresponding elements of |
|
|
LIST. |
|
|
|
|
|
Its anaphoric counterpart is ‘--keep’. |
|
|
|
|
|
(-keep #'cdr '((1 2 3) (4 5) (6))) |
|
|
⇒ ((2 3) (5)) |
|
|
(-keep (lambda (n) (and (> n 3) (* 10 n))) '(1 2 3 4 5 6)) |
|
|
⇒ (40 50 60) |
|
|
(--keep (and (> it 3) (* 10 it)) '(1 2 3 4 5 6)) |
|
|
⇒ (40 50 60) |
|
|
|
|
|
-- Function: -concat (&rest sequences) |
|
|
Concatenate all the arguments and make the result a list. The |
|
|
result is a list whose elements are the elements of all the |
|
|
arguments. Each argument may be a list, vector or string. The |
|
|
last argument is not copied, just used as the tail of the new list. |
|
|
|
|
|
(-concat '(1)) |
|
|
⇒ (1) |
|
|
(-concat '(1) '(2)) |
|
|
⇒ (1 2) |
|
|
(-concat '(1) '(2 3) '(4)) |
|
|
⇒ (1 2 3 4) |
|
|
|
|
|
-- Function: -flatten (l) |
|
|
Take a nested list L and return its contents as a single, flat |
|
|
list. |
|
|
|
|
|
Note that because ‘nil’ represents a list of zero elements (an |
|
|
empty list), any mention of ‘nil’ in L will disappear after |
|
|
flattening. If you need to preserve nils, consider ‘-flatten-n’ |
|
|
(*note -flatten-n::) or map them to some unique symbol and then map |
|
|
them back. |
|
|
|
|
|
Conses of two atoms are considered "terminals", that is, they |
|
|
aren’t flattened further. |
|
|
|
|
|
See also: ‘-flatten-n’ (*note -flatten-n::) |
|
|
|
|
|
(-flatten '((1))) |
|
|
⇒ (1) |
|
|
(-flatten '((1 (2 3) (((4 (5))))))) |
|
|
⇒ (1 2 3 4 5) |
|
|
(-flatten '(1 2 (3 . 4))) |
|
|
⇒ (1 2 (3 . 4)) |
|
|
|
|
|
-- Function: -flatten-n (num list) |
|
|
Flatten NUM levels of a nested LIST. |
|
|
|
|
|
See also: ‘-flatten’ (*note -flatten::) |
|
|
|
|
|
(-flatten-n 1 '((1 2) ((3 4) ((5 6))))) |
|
|
⇒ (1 2 (3 4) ((5 6))) |
|
|
(-flatten-n 2 '((1 2) ((3 4) ((5 6))))) |
|
|
⇒ (1 2 3 4 (5 6)) |
|
|
(-flatten-n 3 '((1 2) ((3 4) ((5 6))))) |
|
|
⇒ (1 2 3 4 5 6) |
|
|
|
|
|
-- Function: -replace (old new list) |
|
|
Replace all OLD items in LIST with NEW. |
|
|
|
|
|
Elements are compared using ‘equal’. |
|
|
|
|
|
See also: ‘-replace-at’ (*note -replace-at::) |
|
|
|
|
|
(-replace 1 "1" '(1 2 3 4 3 2 1)) |
|
|
⇒ ("1" 2 3 4 3 2 "1") |
|
|
(-replace "foo" "bar" '("a" "nice" "foo" "sentence" "about" "foo")) |
|
|
⇒ ("a" "nice" "bar" "sentence" "about" "bar") |
|
|
(-replace 1 2 nil) |
|
|
⇒ nil |
|
|
|
|
|
-- Function: -replace-first (old new list) |
|
|
Replace the first occurrence of OLD with NEW in LIST. |
|
|
|
|
|
Elements are compared using ‘equal’. |
|
|
|
|
|
See also: ‘-map-first’ (*note -map-first::) |
|
|
|
|
|
(-replace-first 1 "1" '(1 2 3 4 3 2 1)) |
|
|
⇒ ("1" 2 3 4 3 2 1) |
|
|
(-replace-first "foo" "bar" '("a" "nice" "foo" "sentence" "about" "foo")) |
|
|
⇒ ("a" "nice" "bar" "sentence" "about" "foo") |
|
|
(-replace-first 1 2 nil) |
|
|
⇒ nil |
|
|
|
|
|
-- Function: -replace-last (old new list) |
|
|
Replace the last occurrence of OLD with NEW in LIST. |
|
|
|
|
|
Elements are compared using ‘equal’. |
|
|
|
|
|
See also: ‘-map-last’ (*note -map-last::) |
|
|
|
|
|
(-replace-last 1 "1" '(1 2 3 4 3 2 1)) |
|
|
⇒ (1 2 3 4 3 2 "1") |
|
|
(-replace-last "foo" "bar" '("a" "nice" "foo" "sentence" "about" "foo")) |
|
|
⇒ ("a" "nice" "foo" "sentence" "about" "bar") |
|
|
(-replace-last 1 2 nil) |
|
|
⇒ nil |
|
|
|
|
|
-- Function: -insert-at (n x list) |
|
|
Return a list with X inserted into LIST at position N. |
|
|
|
|
|
See also: ‘-splice’ (*note -splice::), ‘-splice-list’ (*note |
|
|
-splice-list::) |
|
|
|
|
|
(-insert-at 1 'x '(a b c)) |
|
|
⇒ (a x b c) |
|
|
(-insert-at 12 'x '(a b c)) |
|
|
⇒ (a b c x) |
|
|
|
|
|
-- Function: -replace-at (n x list) |
|
|
Return a list with element at Nth position in LIST replaced with X. |
|
|
|
|
|
See also: ‘-replace’ (*note -replace::) |
|
|
|
|
|
(-replace-at 0 9 '(0 1 2 3 4 5)) |
|
|
⇒ (9 1 2 3 4 5) |
|
|
(-replace-at 1 9 '(0 1 2 3 4 5)) |
|
|
⇒ (0 9 2 3 4 5) |
|
|
(-replace-at 4 9 '(0 1 2 3 4 5)) |
|
|
⇒ (0 1 2 3 9 5) |
|
|
|
|
|
-- Function: -update-at (n func list) |
|
|
Use FUNC to update the Nth element of LIST. Return a copy of LIST |
|
|
where the Nth element is replaced with the result of calling FUNC |
|
|
on it. |
|
|
|
|
|
See also: ‘-map-when’ (*note -map-when::) |
|
|
|
|
|
(-update-at 0 (lambda (x) (+ x 9)) '(0 1 2 3 4 5)) |
|
|
⇒ (9 1 2 3 4 5) |
|
|
(-update-at 1 (lambda (x) (+ x 8)) '(0 1 2 3 4 5)) |
|
|
⇒ (0 9 2 3 4 5) |
|
|
(--update-at 2 (length it) '("foo" "bar" "baz" "quux")) |
|
|
⇒ ("foo" "bar" 3 "quux") |
|
|
|
|
|
-- Function: -remove-at (n list) |
|
|
Return a list with element at Nth position in LIST removed. |
|
|
|
|
|
See also: ‘-remove-at-indices’ (*note -remove-at-indices::), |
|
|
‘-remove’ (*note -remove::) |
|
|
|
|
|
(-remove-at 0 '("0" "1" "2" "3" "4" "5")) |
|
|
⇒ ("1" "2" "3" "4" "5") |
|
|
(-remove-at 1 '("0" "1" "2" "3" "4" "5")) |
|
|
⇒ ("0" "2" "3" "4" "5") |
|
|
(-remove-at 2 '("0" "1" "2" "3" "4" "5")) |
|
|
⇒ ("0" "1" "3" "4" "5") |
|
|
|
|
|
-- Function: -remove-at-indices (indices list) |
|
|
Return a list whose elements are elements from LIST without |
|
|
elements selected as ‘(nth i list)‘ for all i from INDICES. |
|
|
|
|
|
See also: ‘-remove-at’ (*note -remove-at::), ‘-remove’ (*note |
|
|
-remove::) |
|
|
|
|
|
(-remove-at-indices '(0) '("0" "1" "2" "3" "4" "5")) |
|
|
⇒ ("1" "2" "3" "4" "5") |
|
|
(-remove-at-indices '(0 2 4) '("0" "1" "2" "3" "4" "5")) |
|
|
⇒ ("1" "3" "5") |
|
|
(-remove-at-indices '(0 5) '("0" "1" "2" "3" "4" "5")) |
|
|
⇒ ("1" "2" "3" "4") |
|
|
|
|
|
|
|
|
File: dash.info, Node: Reductions, Next: Unfolding, Prev: List to list, Up: Functions |
|
|
|
|
|
2.4 Reductions |
|
|
============== |
|
|
|
|
|
Functions reducing lists to a single value (which may also be a list). |
|
|
|
|
|
-- Function: -reduce-from (fn init list) |
|
|
Reduce the function FN across LIST, starting with INIT. Return the |
|
|
result of applying FN to INIT and the first element of LIST, then |
|
|
applying FN to that result and the second element, etc. If LIST is |
|
|
empty, return INIT without calling FN. |
|
|
|
|
|
This function’s anaphoric counterpart is ‘--reduce-from’. |
|
|
|
|
|
For other folds, see also ‘-reduce’ (*note -reduce::) and |
|
|
‘-reduce-r’ (*note -reduce-r::). |
|
|
|
|
|
(-reduce-from #'- 10 '(1 2 3)) |
|
|
⇒ 4 |
|
|
(-reduce-from #'list 10 '(1 2 3)) |
|
|
⇒ (((10 1) 2) 3) |
|
|
(--reduce-from (concat acc " " it) "START" '("a" "b" "c")) |
|
|
⇒ "START a b c" |
|
|
|
|
|
-- Function: -reduce-r-from (fn init list) |
|
|
Reduce the function FN across LIST in reverse, starting with INIT. |
|
|
Return the result of applying FN to the last element of LIST and |
|
|
INIT, then applying FN to the second-to-last element and the |
|
|
previous result of FN, etc. That is, the first argument of FN is |
|
|
the current element, and its second argument the accumulated value. |
|
|
If LIST is empty, return INIT without calling FN. |
|
|
|
|
|
This function is like ‘-reduce-from’ (*note -reduce-from::) but the |
|
|
operation associates from the right rather than left. In other |
|
|
words, it starts from the end of LIST and flips the arguments to |
|
|
FN. Conceptually, it is like replacing the conses in LIST with |
|
|
applications of FN, and its last link with INIT, and evaluating the |
|
|
resulting expression. |
|
|
|
|
|
This function’s anaphoric counterpart is ‘--reduce-r-from’. |
|
|
|
|
|
For other folds, see also ‘-reduce-r’ (*note -reduce-r::) and |
|
|
‘-reduce’ (*note -reduce::). |
|
|
|
|
|
(-reduce-r-from #'- 10 '(1 2 3)) |
|
|
⇒ -8 |
|
|
(-reduce-r-from #'list 10 '(1 2 3)) |
|
|
⇒ (1 (2 (3 10))) |
|
|
(--reduce-r-from (concat it " " acc) "END" '("a" "b" "c")) |
|
|
⇒ "a b c END" |
|
|
|
|
|
-- Function: -reduce (fn list) |
|
|
Reduce the function FN across LIST. Return the result of applying |
|
|
FN to the first two elements of LIST, then applying FN to that |
|
|
result and the third element, etc. If LIST contains a single |
|
|
element, return it without calling FN. If LIST is empty, return |
|
|
the result of calling FN with no arguments. |
|
|
|
|
|
This function’s anaphoric counterpart is ‘--reduce’. |
|
|
|
|
|
For other folds, see also ‘-reduce-from’ (*note -reduce-from::) and |
|
|
‘-reduce-r’ (*note -reduce-r::). |
|
|
|
|
|
(-reduce #'- '(1 2 3 4)) |
|
|
⇒ -8 |
|
|
(-reduce #'list '(1 2 3 4)) |
|
|
⇒ (((1 2) 3) 4) |
|
|
(--reduce (format "%s-%d" acc it) '(1 2 3)) |
|
|
⇒ "1-2-3" |
|
|
|
|
|
-- Function: -reduce-r (fn list) |
|
|
Reduce the function FN across LIST in reverse. Return the result |
|
|
of applying FN to the last two elements of LIST, then applying FN |
|
|
to the third-to-last element and the previous result of FN, etc. |
|
|
That is, the first argument of FN is the current element, and its |
|
|
second argument the accumulated value. If LIST contains a single |
|
|
element, return it without calling FN. If LIST is empty, return |
|
|
the result of calling FN with no arguments. |
|
|
|
|
|
This function is like ‘-reduce’ (*note -reduce::) but the operation |
|
|
associates from the right rather than left. In other words, it |
|
|
starts from the end of LIST and flips the arguments to FN. |
|
|
Conceptually, it is like replacing the conses in LIST with |
|
|
applications of FN, ignoring its last link, and evaluating the |
|
|
resulting expression. |
|
|
|
|
|
This function’s anaphoric counterpart is ‘--reduce-r’. |
|
|
|
|
|
For other folds, see also ‘-reduce-r-from’ (*note -reduce-r-from::) |
|
|
and ‘-reduce’ (*note -reduce::). |
|
|
|
|
|
(-reduce-r #'- '(1 2 3 4)) |
|
|
⇒ -2 |
|
|
(-reduce-r #'list '(1 2 3 4)) |
|
|
⇒ (1 (2 (3 4))) |
|
|
(--reduce-r (format "%s-%d" acc it) '(1 2 3)) |
|
|
⇒ "3-2-1" |
|
|
|
|
|
-- Function: -reductions-from (fn init list) |
|
|
Return a list of FN’s intermediate reductions across LIST. That |
|
|
is, a list of the intermediate values of the accumulator when |
|
|
‘-reduce-from’ (*note -reduce-from::) (which see) is called with |
|
|
the same arguments. |
|
|
|
|
|
This function’s anaphoric counterpart is ‘--reductions-from’. |
|
|
|
|
|
For other folds, see also ‘-reductions’ (*note -reductions::) and |
|
|
‘-reductions-r’ (*note -reductions-r::). |
|
|
|
|
|
(-reductions-from #'max 0 '(2 1 4 3)) |
|
|
⇒ (0 2 2 4 4) |
|
|
(-reductions-from #'* 1 '(1 2 3 4)) |
|
|
⇒ (1 1 2 6 24) |
|
|
(--reductions-from (format "(FN %s %d)" acc it) "INIT" '(1 2 3)) |
|
|
⇒ ("INIT" "(FN INIT 1)" "(FN (FN INIT 1) 2)" "(FN (FN (FN INIT 1) 2) 3)") |
|
|
|
|
|
-- Function: -reductions-r-from (fn init list) |
|
|
Return a list of FN’s intermediate reductions across reversed LIST. |
|
|
That is, a list of the intermediate values of the accumulator when |
|
|
‘-reduce-r-from’ (*note -reduce-r-from::) (which see) is called |
|
|
with the same arguments. |
|
|
|
|
|
This function’s anaphoric counterpart is ‘--reductions-r-from’. |
|
|
|
|
|
For other folds, see also ‘-reductions’ (*note -reductions::) and |
|
|
‘-reductions-r’ (*note -reductions-r::). |
|
|
|
|
|
(-reductions-r-from #'max 0 '(2 1 4 3)) |
|
|
⇒ (4 4 4 3 0) |
|
|
(-reductions-r-from #'* 1 '(1 2 3 4)) |
|
|
⇒ (24 24 12 4 1) |
|
|
(--reductions-r-from (format "(FN %d %s)" it acc) "INIT" '(1 2 3)) |
|
|
⇒ ("(FN 1 (FN 2 (FN 3 INIT)))" "(FN 2 (FN 3 INIT))" "(FN 3 INIT)" "INIT") |
|
|
|
|
|
-- Function: -reductions (fn list) |
|
|
Return a list of FN’s intermediate reductions across LIST. That |
|
|
is, a list of the intermediate values of the accumulator when |
|
|
‘-reduce’ (*note -reduce::) (which see) is called with the same |
|
|
arguments. |
|
|
|
|
|
This function’s anaphoric counterpart is ‘--reductions’. |
|
|
|
|
|
For other folds, see also ‘-reductions’ (*note -reductions::) and |
|
|
‘-reductions-r’ (*note -reductions-r::). |
|
|
|
|
|
(-reductions #'+ '(1 2 3 4)) |
|
|
⇒ (1 3 6 10) |
|
|
(-reductions #'* '(1 2 3 4)) |
|
|
⇒ (1 2 6 24) |
|
|
(--reductions (format "(FN %s %d)" acc it) '(1 2 3)) |
|
|
⇒ (1 "(FN 1 2)" "(FN (FN 1 2) 3)") |
|
|
|
|
|
-- Function: -reductions-r (fn list) |
|
|
Return a list of FN’s intermediate reductions across reversed LIST. |
|
|
That is, a list of the intermediate values of the accumulator when |
|
|
‘-reduce-r’ (*note -reduce-r::) (which see) is called with the same |
|
|
arguments. |
|
|
|
|
|
This function’s anaphoric counterpart is ‘--reductions-r’. |
|
|
|
|
|
For other folds, see also ‘-reductions-r-from’ (*note |
|
|
-reductions-r-from::) and ‘-reductions’ (*note -reductions::). |
|
|
|
|
|
(-reductions-r #'+ '(1 2 3 4)) |
|
|
⇒ (10 9 7 4) |
|
|
(-reductions-r #'* '(1 2 3 4)) |
|
|
⇒ (24 24 12 4) |
|
|
(--reductions-r (format "(FN %d %s)" it acc) '(1 2 3)) |
|
|
⇒ ("(FN 1 (FN 2 3))" "(FN 2 3)" 3) |
|
|
|
|
|
-- Function: -count (pred list) |
|
|
Counts the number of items in LIST where (PRED item) is non-‘nil’. |
|
|
|
|
|
(-count 'even? '(1 2 3 4 5)) |
|
|
⇒ 2 |
|
|
(--count (< it 4) '(1 2 3 4)) |
|
|
⇒ 3 |
|
|
|
|
|
-- Function: -sum (list) |
|
|
Return the sum of LIST. |
|
|
|
|
|
(-sum ()) |
|
|
⇒ 0 |
|
|
(-sum '(1)) |
|
|
⇒ 1 |
|
|
(-sum '(1 2 3 4)) |
|
|
⇒ 10 |
|
|
|
|
|
-- Function: -running-sum (list) |
|
|
Return a list with running sums of items in LIST. LIST must be |
|
|
non-empty. |
|
|
|
|
|
(-running-sum '(1 2 3 4)) |
|
|
⇒ (1 3 6 10) |
|
|
(-running-sum '(1)) |
|
|
⇒ (1) |
|
|
(-running-sum ()) |
|
|
error→ Wrong type argument: consp, nil |
|
|
|
|
|
-- Function: -product (list) |
|
|
Return the product of LIST. |
|
|
|
|
|
(-product ()) |
|
|
⇒ 1 |
|
|
(-product '(1)) |
|
|
⇒ 1 |
|
|
(-product '(1 2 3 4)) |
|
|
⇒ 24 |
|
|
|
|
|
-- Function: -running-product (list) |
|
|
Return a list with running products of items in LIST. LIST must be |
|
|
non-empty. |
|
|
|
|
|
(-running-product '(1 2 3 4)) |
|
|
⇒ (1 2 6 24) |
|
|
(-running-product '(1)) |
|
|
⇒ (1) |
|
|
(-running-product ()) |
|
|
error→ Wrong type argument: consp, nil |
|
|
|
|
|
-- Function: -inits (list) |
|
|
Return all prefixes of LIST. |
|
|
|
|
|
(-inits '(1 2 3 4)) |
|
|
⇒ (nil (1) (1 2) (1 2 3) (1 2 3 4)) |
|
|
(-inits nil) |
|
|
⇒ (nil) |
|
|
(-inits '(1)) |
|
|
⇒ (nil (1)) |
|
|
|
|
|
-- Function: -tails (list) |
|
|
Return all suffixes of LIST |
|
|
|
|
|
(-tails '(1 2 3 4)) |
|
|
⇒ ((1 2 3 4) (2 3 4) (3 4) (4) nil) |
|
|
(-tails nil) |
|
|
⇒ (nil) |
|
|
(-tails '(1)) |
|
|
⇒ ((1) nil) |
|
|
|
|
|
-- Function: -common-prefix (&rest lists) |
|
|
Return the longest common prefix of LISTS. |
|
|
|
|
|
(-common-prefix '(1)) |
|
|
⇒ (1) |
|
|
(-common-prefix '(1 2) '(3 4) '(1 2)) |
|
|
⇒ () |
|
|
(-common-prefix '(1 2) '(1 2 3) '(1 2 3 4)) |
|
|
⇒ (1 2) |
|
|
|
|
|
-- Function: -common-suffix (&rest lists) |
|
|
Return the longest common suffix of LISTS. |
|
|
|
|
|
(-common-suffix '(1)) |
|
|
⇒ (1) |
|
|
(-common-suffix '(1 2) '(3 4) '(1 2)) |
|
|
⇒ () |
|
|
(-common-suffix '(1 2 3 4) '(2 3 4) '(3 4)) |
|
|
⇒ (3 4) |
|
|
|
|
|
-- Function: -min (list) |
|
|
Return the smallest value from LIST of numbers or markers. |
|
|
|
|
|
(-min '(0)) |
|
|
⇒ 0 |
|
|
(-min '(3 2 1)) |
|
|
⇒ 1 |
|
|
(-min '(1 2 3)) |
|
|
⇒ 1 |
|
|
|
|
|
-- Function: -min-by (comparator list) |
|
|
Take a comparison function COMPARATOR and a LIST and return the |
|
|
least element of the list by the comparison function. |
|
|
|
|
|
See also combinator ‘-on’ (*note -on::) which can transform the |
|
|
values before comparing them. |
|
|
|
|
|
(-min-by '> '(4 3 6 1)) |
|
|
⇒ 1 |
|
|
(--min-by (> (car it) (car other)) '((1 2 3) (2) (3 2))) |
|
|
⇒ (1 2 3) |
|
|
(--min-by (> (length it) (length other)) '((1 2 3) (2) (3 2))) |
|
|
⇒ (2) |
|
|
|
|
|
-- Function: -max (list) |
|
|
Return the largest value from LIST of numbers or markers. |
|
|
|
|
|
(-max '(0)) |
|
|
⇒ 0 |
|
|
(-max '(3 2 1)) |
|
|
⇒ 3 |
|
|
(-max '(1 2 3)) |
|
|
⇒ 3 |
|
|
|
|
|
-- Function: -max-by (comparator list) |
|
|
Take a comparison function COMPARATOR and a LIST and return the |
|
|
greatest element of the list by the comparison function. |
|
|
|
|
|
See also combinator ‘-on’ (*note -on::) which can transform the |
|
|
values before comparing them. |
|
|
|
|
|
(-max-by '> '(4 3 6 1)) |
|
|
⇒ 6 |
|
|
(--max-by (> (car it) (car other)) '((1 2 3) (2) (3 2))) |
|
|
⇒ (3 2) |
|
|
(--max-by (> (length it) (length other)) '((1 2 3) (2) (3 2))) |
|
|
⇒ (1 2 3) |
|
|
|
|
|
|
|
|
File: dash.info, Node: Unfolding, Next: Predicates, Prev: Reductions, Up: Functions |
|
|
|
|
|
2.5 Unfolding |
|
|
============= |
|
|
|
|
|
Operations dual to reductions, building lists from a seed value rather |
|
|
than consuming a list to produce a single value. |
|
|
|
|
|
-- Function: -iterate (fun init n) |
|
|
Return a list of iterated applications of FUN to INIT. |
|
|
|
|
|
This means a list of the form: |
|
|
|
|
|
(INIT (FUN INIT) (FUN (FUN INIT)) ...) |
|
|
|
|
|
N is the length of the returned list. |
|
|
|
|
|
(-iterate #'1+ 1 10) |
|
|
⇒ (1 2 3 4 5 6 7 8 9 10) |
|
|
(-iterate (lambda (x) (+ x x)) 2 5) |
|
|
⇒ (2 4 8 16 32) |
|
|
(--iterate (* it it) 2 5) |
|
|
⇒ (2 4 16 256 65536) |
|
|
|
|
|
-- Function: -unfold (fun seed) |
|
|
Build a list from SEED using FUN. |
|
|
|
|
|
This is "dual" operation to ‘-reduce-r’ (*note -reduce-r::): while |
|
|
-reduce-r consumes a list to produce a single value, ‘-unfold’ |
|
|
(*note -unfold::) takes a seed value and builds a (potentially |
|
|
infinite!) list. |
|
|
|
|
|
FUN should return ‘nil’ to stop the generating process, or a cons |
|
|
(A . B), where A will be prepended to the result and B is the new |
|
|
seed. |
|
|
|
|
|
(-unfold (lambda (x) (unless (= x 0) (cons x (1- x)))) 10) |
|
|
⇒ (10 9 8 7 6 5 4 3 2 1) |
|
|
(--unfold (when it (cons it (cdr it))) '(1 2 3 4)) |
|
|
⇒ ((1 2 3 4) (2 3 4) (3 4) (4)) |
|
|
(--unfold (when it (cons it (butlast it))) '(1 2 3 4)) |
|
|
⇒ ((1 2 3 4) (1 2 3) (1 2) (1)) |
|
|
|
|
|
|
|
|
File: dash.info, Node: Predicates, Next: Partitioning, Prev: Unfolding, Up: Functions |
|
|
|
|
|
2.6 Predicates |
|
|
============== |
|
|
|
|
|
Reductions of one or more lists to a boolean value. |
|
|
|
|
|
-- Function: -some (pred list) |
|
|
Return (PRED x) for the first LIST item where (PRED x) is |
|
|
non-‘nil’, else ‘nil’. |
|
|
|
|
|
Alias: ‘-any’. |
|
|
|
|
|
This function’s anaphoric counterpart is ‘--some’. |
|
|
|
|
|
(-some #'stringp '(1 "2" 3)) |
|
|
⇒ t |
|
|
(--some (string-match-p "x" it) '("foo" "axe" "xor")) |
|
|
⇒ 1 |
|
|
(--some (= it-index 3) '(0 1 2)) |
|
|
⇒ nil |
|
|
|
|
|
-- Function: -every (pred list) |
|
|
Return non-‘nil’ if PRED returns non-‘nil’ for all items in LIST. |
|
|
If so, return the last such result of PRED. Otherwise, once an |
|
|
item is reached for which PRED returns ‘nil’, return ‘nil’ without |
|
|
calling PRED on any further LIST elements. |
|
|
|
|
|
This function is like ‘-every-p’, but on success returns the last |
|
|
non-‘nil’ result of PRED instead of just ‘t’. |
|
|
|
|
|
This function’s anaphoric counterpart is ‘--every’. |
|
|
|
|
|
(-every #'numberp '(1 2 3)) |
|
|
⇒ t |
|
|
(--every (string-match-p "x" it) '("axe" "xor")) |
|
|
⇒ 0 |
|
|
(--every (= it it-index) '(0 1 3)) |
|
|
⇒ nil |
|
|
|
|
|
-- Function: -any? (pred list) |
|
|
Return ‘t’ if (PRED X) is non-‘nil’ for any X in LIST, else ‘nil’. |
|
|
|
|
|
Alias: ‘-any-p’, ‘-some?’, ‘-some-p’ |
|
|
|
|
|
(-any? #'numberp '(nil 0 t)) |
|
|
⇒ t |
|
|
(-any? #'numberp '(nil t t)) |
|
|
⇒ nil |
|
|
(-any? #'null '(1 3 5)) |
|
|
⇒ nil |
|
|
|
|
|
-- Function: -all? (pred list) |
|
|
Return ‘t’ if (PRED X) is non-‘nil’ for all X in LIST, else ‘nil’. |
|
|
In the latter case, stop after the first X for which (PRED X) is |
|
|
‘nil’, without calling PRED on any subsequent elements of LIST. |
|
|
|
|
|
The similar function ‘-every’ (*note -every::) is more widely |
|
|
useful, since it returns the last non-‘nil’ result of PRED instead |
|
|
of just ‘t’ on success. |
|
|
|
|
|
Alias: ‘-all-p’, ‘-every-p’, ‘-every?’. |
|
|
|
|
|
This function’s anaphoric counterpart is ‘--all?’. |
|
|
|
|
|
(-all? #'numberp '(1 2 3)) |
|
|
⇒ t |
|
|
(-all? #'numberp '(2 t 6)) |
|
|
⇒ nil |
|
|
(--all? (= 0 (% it 2)) '(2 4 6)) |
|
|
⇒ t |
|
|
|
|
|
-- Function: -none? (pred list) |
|
|
Return ‘t’ if (PRED X) is ‘nil’ for all X in LIST, else ‘nil’. |
|
|
|
|
|
Alias: ‘-none-p’ |
|
|
|
|
|
(-none? 'even? '(1 2 3)) |
|
|
⇒ nil |
|
|
(-none? 'even? '(1 3 5)) |
|
|
⇒ t |
|
|
(--none? (= 0 (% it 2)) '(1 2 3)) |
|
|
⇒ nil |
|
|
|
|
|
-- Function: -only-some? (pred list) |
|
|
Return ‘t’ if different LIST items both satisfy and do not satisfy |
|
|
PRED. That is, if PRED returns both ‘nil’ for at least one item, |
|
|
and non-‘nil’ for at least one other item in LIST. Return ‘nil’ if |
|
|
all items satisfy the predicate or none of them do. |
|
|
|
|
|
Alias: ‘-only-some-p’ |
|
|
|
|
|
(-only-some? 'even? '(1 2 3)) |
|
|
⇒ t |
|
|
(-only-some? 'even? '(1 3 5)) |
|
|
⇒ nil |
|
|
(-only-some? 'even? '(2 4 6)) |
|
|
⇒ nil |
|
|
|
|
|
-- Function: -contains? (list element) |
|
|
Return non-‘nil’ if LIST contains ELEMENT. |
|
|
|
|
|
The test for equality is done with ‘equal’, or with ‘-compare-fn’ |
|
|
if that’s non-‘nil’. |
|
|
|
|
|
Alias: ‘-contains-p’ |
|
|
|
|
|
(-contains? '(1 2 3) 1) |
|
|
⇒ t |
|
|
(-contains? '(1 2 3) 2) |
|
|
⇒ t |
|
|
(-contains? '(1 2 3) 4) |
|
|
⇒ nil |
|
|
|
|
|
-- Function: -same-items? (list list2) |
|
|
Return true if LIST and LIST2 has the same items. |
|
|
|
|
|
The order of the elements in the lists does not matter. |
|
|
|
|
|
Alias: ‘-same-items-p’ |
|
|
|
|
|
(-same-items? '(1 2 3) '(1 2 3)) |
|
|
⇒ t |
|
|
(-same-items? '(1 2 3) '(3 2 1)) |
|
|
⇒ t |
|
|
(-same-items? '(1 2 3) '(1 2 3 4)) |
|
|
⇒ nil |
|
|
|
|
|
-- Function: -is-prefix? (prefix list) |
|
|
Return non-‘nil’ if PREFIX is a prefix of LIST. |
|
|
|
|
|
Alias: ‘-is-prefix-p’. |
|
|
|
|
|
(-is-prefix? '(1 2 3) '(1 2 3 4 5)) |
|
|
⇒ t |
|
|
(-is-prefix? '(1 2 3 4 5) '(1 2 3)) |
|
|
⇒ nil |
|
|
(-is-prefix? '(1 3) '(1 2 3 4 5)) |
|
|
⇒ nil |
|
|
|
|
|
-- Function: -is-suffix? (suffix list) |
|
|
Return non-‘nil’ if SUFFIX is a suffix of LIST. |
|
|
|
|
|
Alias: ‘-is-suffix-p’. |
|
|
|
|
|
(-is-suffix? '(3 4 5) '(1 2 3 4 5)) |
|
|
⇒ t |
|
|
(-is-suffix? '(1 2 3 4 5) '(3 4 5)) |
|
|
⇒ nil |
|
|
(-is-suffix? '(3 5) '(1 2 3 4 5)) |
|
|
⇒ nil |
|
|
|
|
|
-- Function: -is-infix? (infix list) |
|
|
Return non-‘nil’ if INFIX is infix of LIST. |
|
|
|
|
|
This operation runs in O(n^2) time |
|
|
|
|
|
Alias: ‘-is-infix-p’ |
|
|
|
|
|
(-is-infix? '(1 2 3) '(1 2 3 4 5)) |
|
|
⇒ t |
|
|
(-is-infix? '(2 3 4) '(1 2 3 4 5)) |
|
|
⇒ t |
|
|
(-is-infix? '(3 4 5) '(1 2 3 4 5)) |
|
|
⇒ t |
|
|
|
|
|
-- Function: -cons-pair? (obj) |
|
|
Return non-‘nil’ if OBJ is a true cons pair. That is, a cons (A . |
|
|
B) where B is not a list. |
|
|
|
|
|
Alias: ‘-cons-pair-p’. |
|
|
|
|
|
(-cons-pair? '(1 . 2)) |
|
|
⇒ t |
|
|
(-cons-pair? '(1 2)) |
|
|
⇒ nil |
|
|
(-cons-pair? '(1)) |
|
|
⇒ nil |
|
|
|
|
|
|
|
|
File: dash.info, Node: Partitioning, Next: Indexing, Prev: Predicates, Up: Functions |
|
|
|
|
|
2.7 Partitioning |
|
|
================ |
|
|
|
|
|
Functions partitioning the input list into a list of lists. |
|
|
|
|
|
-- Function: -split-at (n list) |
|
|
Split LIST into two sublists after the Nth element. The result is |
|
|
a list of two elements (TAKE DROP) where TAKE is a new list of the |
|
|
first N elements of LIST, and DROP is the remaining elements of |
|
|
LIST (not a copy). TAKE and DROP are like the results of ‘-take’ |
|
|
(*note -take::) and ‘-drop’ (*note -drop::), respectively, but the |
|
|
split is done in a single list traversal. |
|
|
|
|
|
(-split-at 3 '(1 2 3 4 5)) |
|
|
⇒ ((1 2 3) (4 5)) |
|
|
(-split-at 17 '(1 2 3 4 5)) |
|
|
⇒ ((1 2 3 4 5) nil) |
|
|
(-split-at 0 '(1 2 3 4 5)) |
|
|
⇒ (nil (1 2 3 4 5)) |
|
|
|
|
|
-- Function: -split-with (pred list) |
|
|
Split LIST into a prefix satisfying PRED, and the rest. The first |
|
|
sublist is the prefix of LIST with successive elements satisfying |
|
|
PRED, and the second sublist is the remaining elements that do not. |
|
|
The result is like performing |
|
|
|
|
|
((-take-while PRED LIST) (-drop-while PRED LIST)) |
|
|
|
|
|
but in no more than a single pass through LIST. |
|
|
|
|
|
(-split-with 'even? '(1 2 3 4)) |
|
|
⇒ (nil (1 2 3 4)) |
|
|
(-split-with 'even? '(2 4 5 6)) |
|
|
⇒ ((2 4) (5 6)) |
|
|
(--split-with (< it 4) '(1 2 3 4 3 2 1)) |
|
|
⇒ ((1 2 3) (4 3 2 1)) |
|
|
|
|
|
-- Macro: -split-on (item list) |
|
|
Split the LIST each time ITEM is found. |
|
|
|
|
|
Unlike ‘-partition-by’ (*note -partition-by::), the ITEM is |
|
|
discarded from the results. Empty lists are also removed from the |
|
|
result. |
|
|
|
|
|
Comparison is done by ‘equal’. |
|
|
|
|
|
See also ‘-split-when’ (*note -split-when::) |
|
|
|
|
|
(-split-on '| '(Nil | Leaf a | Node [Tree a])) |
|
|
⇒ ((Nil) (Leaf a) (Node [Tree a])) |
|
|
(-split-on :endgroup '("a" "b" :endgroup "c" :endgroup "d" "e")) |
|
|
⇒ (("a" "b") ("c") ("d" "e")) |
|
|
(-split-on :endgroup '("a" "b" :endgroup :endgroup "d" "e")) |
|
|
⇒ (("a" "b") ("d" "e")) |
|
|
|
|
|
-- Function: -split-when (fn list) |
|
|
Split the LIST on each element where FN returns non-‘nil’. |
|
|
|
|
|
Unlike ‘-partition-by’ (*note -partition-by::), the "matched" |
|
|
element is discarded from the results. Empty lists are also |
|
|
removed from the result. |
|
|
|
|
|
This function can be thought of as a generalization of |
|
|
‘split-string’. |
|
|
|
|
|
(-split-when 'even? '(1 2 3 4 5 6)) |
|
|
⇒ ((1) (3) (5)) |
|
|
(-split-when 'even? '(1 2 3 4 6 8 9)) |
|
|
⇒ ((1) (3) (9)) |
|
|
(--split-when (memq it '(&optional &rest)) '(a b &optional c d &rest args)) |
|
|
⇒ ((a b) (c d) (args)) |
|
|
|
|
|
-- Function: -separate (pred list) |
|
|
Split LIST into two sublists based on whether items satisfy PRED. |
|
|
The result is like performing |
|
|
|
|
|
((-filter PRED LIST) (-remove PRED LIST)) |
|
|
|
|
|
but in a single pass through LIST. |
|
|
|
|
|
(-separate (lambda (num) (= 0 (% num 2))) '(1 2 3 4 5 6 7)) |
|
|
⇒ ((2 4 6) (1 3 5 7)) |
|
|
(--separate (< it 5) '(3 7 5 9 3 2 1 4 6)) |
|
|
⇒ ((3 3 2 1 4) (7 5 9 6)) |
|
|
(-separate 'cdr '((1 2) (1) (1 2 3) (4))) |
|
|
⇒ (((1 2) (1 2 3)) ((1) (4))) |
|
|
|
|
|
-- Function: -partition (n list) |
|
|
Return a new list with the items in LIST grouped into N-sized |
|
|
sublists. If there are not enough items to make the last group |
|
|
N-sized, those items are discarded. |
|
|
|
|
|
(-partition 2 '(1 2 3 4 5 6)) |
|
|
⇒ ((1 2) (3 4) (5 6)) |
|
|
(-partition 2 '(1 2 3 4 5 6 7)) |
|
|
⇒ ((1 2) (3 4) (5 6)) |
|
|
(-partition 3 '(1 2 3 4 5 6 7)) |
|
|
⇒ ((1 2 3) (4 5 6)) |
|
|
|
|
|
-- Function: -partition-all (n list) |
|
|
Return a new list with the items in LIST grouped into N-sized |
|
|
sublists. The last group may contain less than N items. |
|
|
|
|
|
(-partition-all 2 '(1 2 3 4 5 6)) |
|
|
⇒ ((1 2) (3 4) (5 6)) |
|
|
(-partition-all 2 '(1 2 3 4 5 6 7)) |
|
|
⇒ ((1 2) (3 4) (5 6) (7)) |
|
|
(-partition-all 3 '(1 2 3 4 5 6 7)) |
|
|
⇒ ((1 2 3) (4 5 6) (7)) |
|
|
|
|
|
-- Function: -partition-in-steps (n step list) |
|
|
Partition LIST into sublists of length N that are STEP items apart. |
|
|
Like ‘-partition-all-in-steps’ (*note -partition-all-in-steps::), |
|
|
but if there are not enough items to make the last group N-sized, |
|
|
those items are discarded. |
|
|
|
|
|
(-partition-in-steps 2 1 '(1 2 3 4)) |
|
|
⇒ ((1 2) (2 3) (3 4)) |
|
|
(-partition-in-steps 3 2 '(1 2 3 4)) |
|
|
⇒ ((1 2 3)) |
|
|
(-partition-in-steps 3 2 '(1 2 3 4 5)) |
|
|
⇒ ((1 2 3) (3 4 5)) |
|
|
|
|
|
-- Function: -partition-all-in-steps (n step list) |
|
|
Partition LIST into sublists of length N that are STEP items apart. |
|
|
Adjacent groups may overlap if N exceeds the STEP stride. Trailing |
|
|
groups may contain less than N items. |
|
|
|
|
|
(-partition-all-in-steps 2 1 '(1 2 3 4)) |
|
|
⇒ ((1 2) (2 3) (3 4) (4)) |
|
|
(-partition-all-in-steps 3 2 '(1 2 3 4)) |
|
|
⇒ ((1 2 3) (3 4)) |
|
|
(-partition-all-in-steps 3 2 '(1 2 3 4 5)) |
|
|
⇒ ((1 2 3) (3 4 5) (5)) |
|
|
|
|
|
-- Function: -partition-by (fn list) |
|
|
Apply FN to each item in LIST, splitting it each time FN returns a |
|
|
new value. |
|
|
|
|
|
(-partition-by 'even? ()) |
|
|
⇒ () |
|
|
(-partition-by 'even? '(1 1 2 2 2 3 4 6 8)) |
|
|
⇒ ((1 1) (2 2 2) (3) (4 6 8)) |
|
|
(--partition-by (< it 3) '(1 2 3 4 3 2 1)) |
|
|
⇒ ((1 2) (3 4 3) (2 1)) |
|
|
|
|
|
-- Function: -partition-by-header (fn list) |
|
|
Apply FN to the first item in LIST. That is the header value. |
|
|
Apply FN to each item in LIST, splitting it each time FN returns |
|
|
the header value, but only after seeing at least one other value |
|
|
(the body). |
|
|
|
|
|
(--partition-by-header (= it 1) '(1 2 3 1 2 1 2 3 4)) |
|
|
⇒ ((1 2 3) (1 2) (1 2 3 4)) |
|
|
(--partition-by-header (> it 0) '(1 2 0 1 0 1 2 3 0)) |
|
|
⇒ ((1 2 0) (1 0) (1 2 3 0)) |
|
|
(-partition-by-header 'even? '(2 1 1 1 4 1 3 5 6 6 1)) |
|
|
⇒ ((2 1 1 1) (4 1 3 5) (6 6 1)) |
|
|
|
|
|
-- Function: -partition-after-pred (pred list) |
|
|
Partition LIST after each element for which PRED returns non-‘nil’. |
|
|
|
|
|
This function’s anaphoric counterpart is ‘--partition-after-pred’. |
|
|
|
|
|
(-partition-after-pred #'booleanp ()) |
|
|
⇒ () |
|
|
(-partition-after-pred #'booleanp '(t t)) |
|
|
⇒ ((t) (t)) |
|
|
(-partition-after-pred #'booleanp '(0 0 t t 0 t)) |
|
|
⇒ ((0 0 t) (t) (0 t)) |
|
|
|
|
|
-- Function: -partition-before-pred (pred list) |
|
|
Partition directly before each time PRED is true on an element of |
|
|
LIST. |
|
|
|
|
|
(-partition-before-pred #'booleanp ()) |
|
|
⇒ () |
|
|
(-partition-before-pred #'booleanp '(0 t)) |
|
|
⇒ ((0) (t)) |
|
|
(-partition-before-pred #'booleanp '(0 0 t 0 t t)) |
|
|
⇒ ((0 0) (t 0) (t) (t)) |
|
|
|
|
|
-- Function: -partition-before-item (item list) |
|
|
Partition directly before each time ITEM appears in LIST. |
|
|
|
|
|
(-partition-before-item 3 ()) |
|
|
⇒ () |
|
|
(-partition-before-item 3 '(1)) |
|
|
⇒ ((1)) |
|
|
(-partition-before-item 3 '(3)) |
|
|
⇒ ((3)) |
|
|
|
|
|
-- Function: -partition-after-item (item list) |
|
|
Partition directly after each time ITEM appears in LIST. |
|
|
|
|
|
(-partition-after-item 3 ()) |
|
|
⇒ () |
|
|
(-partition-after-item 3 '(1)) |
|
|
⇒ ((1)) |
|
|
(-partition-after-item 3 '(3)) |
|
|
⇒ ((3)) |
|
|
|
|
|
-- Function: -group-by (fn list) |
|
|
Separate LIST into an alist whose keys are FN applied to the |
|
|
elements of LIST. Keys are compared by ‘equal’. |
|
|
|
|
|
(-group-by 'even? ()) |
|
|
⇒ () |
|
|
(-group-by 'even? '(1 1 2 2 2 3 4 6 8)) |
|
|
⇒ ((nil 1 1 3) (t 2 2 2 4 6 8)) |
|
|
(--group-by (car (split-string it "/")) '("a/b" "c/d" "a/e")) |
|
|
⇒ (("a" "a/b" "a/e") ("c" "c/d")) |
|
|
|
|
|
|
|
|
File: dash.info, Node: Indexing, Next: Set operations, Prev: Partitioning, Up: Functions |
|
|
|
|
|
2.8 Indexing |
|
|
============ |
|
|
|
|
|
Functions retrieving or sorting based on list indices and related |
|
|
predicates. |
|
|
|
|
|
-- Function: -elem-index (elem list) |
|
|
Return the index of the first element in the given LIST which is |
|
|
equal to the query element ELEM, or ‘nil’ if there is no such |
|
|
element. |
|
|
|
|
|
(-elem-index 2 '(6 7 8 2 3 4)) |
|
|
⇒ 3 |
|
|
(-elem-index "bar" '("foo" "bar" "baz")) |
|
|
⇒ 1 |
|
|
(-elem-index '(1 2) '((3) (5 6) (1 2) nil)) |
|
|
⇒ 2 |
|
|
|
|
|
-- Function: -elem-indices (elem list) |
|
|
Return the indices of all elements in LIST equal to the query |
|
|
element ELEM, in ascending order. |
|
|
|
|
|
(-elem-indices 2 '(6 7 8 2 3 4 2 1)) |
|
|
⇒ (3 6) |
|
|
(-elem-indices "bar" '("foo" "bar" "baz")) |
|
|
⇒ (1) |
|
|
(-elem-indices '(1 2) '((3) (1 2) (5 6) (1 2) nil)) |
|
|
⇒ (1 3) |
|
|
|
|
|
-- Function: -find-index (pred list) |
|
|
Take a predicate PRED and a LIST and return the index of the first |
|
|
element in the list satisfying the predicate, or ‘nil’ if there is |
|
|
no such element. |
|
|
|
|
|
See also ‘-first’ (*note -first::). |
|
|
|
|
|
(-find-index 'even? '(2 4 1 6 3 3 5 8)) |
|
|
⇒ 0 |
|
|
(--find-index (< 5 it) '(2 4 1 6 3 3 5 8)) |
|
|
⇒ 3 |
|
|
(-find-index (-partial 'string-lessp "baz") '("bar" "foo" "baz")) |
|
|
⇒ 1 |
|
|
|
|
|
-- Function: -find-last-index (pred list) |
|
|
Take a predicate PRED and a LIST and return the index of the last |
|
|
element in the list satisfying the predicate, or ‘nil’ if there is |
|
|
no such element. |
|
|
|
|
|
See also ‘-last’ (*note -last::). |
|
|
|
|
|
(-find-last-index 'even? '(2 4 1 6 3 3 5 8)) |
|
|
⇒ 7 |
|
|
(--find-last-index (< 5 it) '(2 7 1 6 3 8 5 2)) |
|
|
⇒ 5 |
|
|
(-find-last-index (-partial 'string-lessp "baz") '("q" "foo" "baz")) |
|
|
⇒ 1 |
|
|
|
|
|
-- Function: -find-indices (pred list) |
|
|
Return the indices of all elements in LIST satisfying the predicate |
|
|
PRED, in ascending order. |
|
|
|
|
|
(-find-indices 'even? '(2 4 1 6 3 3 5 8)) |
|
|
⇒ (0 1 3 7) |
|
|
(--find-indices (< 5 it) '(2 4 1 6 3 3 5 8)) |
|
|
⇒ (3 7) |
|
|
(-find-indices (-partial 'string-lessp "baz") '("bar" "foo" "baz")) |
|
|
⇒ (1) |
|
|
|
|
|
-- Function: -grade-up (comparator list) |
|
|
Grade elements of LIST using COMPARATOR relation. This yields a |
|
|
permutation vector such that applying this permutation to LIST |
|
|
sorts it in ascending order. |
|
|
|
|
|
(-grade-up #'< '(3 1 4 2 1 3 3)) |
|
|
⇒ (1 4 3 0 5 6 2) |
|
|
(let ((l '(3 1 4 2 1 3 3))) (-select-by-indices (-grade-up #'< l) l)) |
|
|
⇒ (1 1 2 3 3 3 4) |
|
|
|
|
|
-- Function: -grade-down (comparator list) |
|
|
Grade elements of LIST using COMPARATOR relation. This yields a |
|
|
permutation vector such that applying this permutation to LIST |
|
|
sorts it in descending order. |
|
|
|
|
|
(-grade-down #'< '(3 1 4 2 1 3 3)) |
|
|
⇒ (2 0 5 6 3 1 4) |
|
|
(let ((l '(3 1 4 2 1 3 3))) (-select-by-indices (-grade-down #'< l) l)) |
|
|
⇒ (4 3 3 3 2 1 1) |
|
|
|
|
|
|
|
|
File: dash.info, Node: Set operations, Next: Other list operations, Prev: Indexing, Up: Functions |
|
|
|
|
|
2.9 Set operations |
|
|
================== |
|
|
|
|
|
Operations pretending lists are sets. |
|
|
|
|
|
-- Function: -union (list list2) |
|
|
Return a new list of all elements appearing in either LIST1 or |
|
|
LIST2. Equality is defined by the value of ‘-compare-fn’ if |
|
|
non-‘nil’; otherwise ‘equal’. |
|
|
|
|
|
(-union '(1 2 3) '(3 4 5)) |
|
|
⇒ (1 2 3 4 5) |
|
|
(-union '(1 2 3 4) ()) |
|
|
⇒ (1 2 3 4) |
|
|
(-union '(1 1 2 2) '(3 2 1)) |
|
|
⇒ (1 1 2 2 3) |
|
|
|
|
|
-- Function: -difference (list list2) |
|
|
Return a new list with only the members of LIST that are not in |
|
|
LIST2. The test for equality is done with ‘equal’, or with |
|
|
‘-compare-fn’ if that’s non-‘nil’. |
|
|
|
|
|
(-difference () ()) |
|
|
⇒ () |
|
|
(-difference '(1 2 3) '(4 5 6)) |
|
|
⇒ (1 2 3) |
|
|
(-difference '(1 2 3 4) '(3 4 5 6)) |
|
|
⇒ (1 2) |
|
|
|
|
|
-- Function: -intersection (list list2) |
|
|
Return a new list of the elements appearing in both LIST1 and |
|
|
LIST2. Equality is defined by the value of ‘-compare-fn’ if |
|
|
non-‘nil’; otherwise ‘equal’. |
|
|
|
|
|
(-intersection () ()) |
|
|
⇒ () |
|
|
(-intersection '(1 2 3) '(4 5 6)) |
|
|
⇒ () |
|
|
(-intersection '(1 2 3 4) '(3 4 5 6)) |
|
|
⇒ (3 4) |
|
|
|
|
|
-- Function: -powerset (list) |
|
|
Return the power set of LIST. |
|
|
|
|
|
(-powerset ()) |
|
|
⇒ (nil) |
|
|
(-powerset '(x y z)) |
|
|
⇒ ((x y z) (x y) (x z) (x) (y z) (y) (z) nil) |
|
|
|
|
|
-- Function: -permutations (list) |
|
|
Return the permutations of LIST. |
|
|
|
|
|
(-permutations ()) |
|
|
⇒ (nil) |
|
|
(-permutations '(1 2)) |
|
|
⇒ ((1 2) (2 1)) |
|
|
(-permutations '(a b c)) |
|
|
⇒ ((a b c) (a c b) (b a c) (b c a) (c a b) (c b a)) |
|
|
|
|
|
-- Function: -distinct (list) |
|
|
Return a new list with all duplicates removed. The test for |
|
|
equality is done with ‘equal’, or with ‘-compare-fn’ if that’s |
|
|
non-‘nil’. |
|
|
|
|
|
Alias: ‘-uniq’ |
|
|
|
|
|
(-distinct ()) |
|
|
⇒ () |
|
|
(-distinct '(1 2 2 4)) |
|
|
⇒ (1 2 4) |
|
|
(-distinct '(t t t)) |
|
|
⇒ (t) |
|
|
|
|
|
|
|
|
File: dash.info, Node: Other list operations, Next: Tree operations, Prev: Set operations, Up: Functions |
|
|
|
|
|
2.10 Other list operations |
|
|
========================== |
|
|
|
|
|
Other list functions not fit to be classified elsewhere. |
|
|
|
|
|
-- Function: -rotate (n list) |
|
|
Rotate LIST N places to the right (left if N is negative). The |
|
|
time complexity is O(n). |
|
|
|
|
|
(-rotate 3 '(1 2 3 4 5 6 7)) |
|
|
⇒ (5 6 7 1 2 3 4) |
|
|
(-rotate -3 '(1 2 3 4 5 6 7)) |
|
|
⇒ (4 5 6 7 1 2 3) |
|
|
(-rotate 16 '(1 2 3 4 5 6 7)) |
|
|
⇒ (6 7 1 2 3 4 5) |
|
|
|
|
|
-- Function: -repeat (n x) |
|
|
Return a new list of length N with each element being X. Return |
|
|
‘nil’ if N is less than 1. |
|
|
|
|
|
(-repeat 3 :a) |
|
|
⇒ (:a :a :a) |
|
|
(-repeat 1 :a) |
|
|
⇒ (:a) |
|
|
(-repeat 0 :a) |
|
|
⇒ nil |
|
|
|
|
|
-- Function: -cons* (&rest args) |
|
|
Make a new list from the elements of ARGS. The last 2 elements of |
|
|
ARGS are used as the final cons of the result, so if the final |
|
|
element of ARGS is not a list, the result is a dotted list. With |
|
|
no ARGS, return ‘nil’. |
|
|
|
|
|
(-cons* 1 2) |
|
|
⇒ (1 . 2) |
|
|
(-cons* 1 2 3) |
|
|
⇒ (1 2 . 3) |
|
|
(-cons* 1) |
|
|
⇒ 1 |
|
|
|
|
|
-- Function: -snoc (list elem &rest elements) |
|
|
Append ELEM to the end of the list. |
|
|
|
|
|
This is like ‘cons’, but operates on the end of list. |
|
|
|
|
|
If any ELEMENTS are given, append them to the list as well. |
|
|
|
|
|
(-snoc '(1 2 3) 4) |
|
|
⇒ (1 2 3 4) |
|
|
(-snoc '(1 2 3) 4 5 6) |
|
|
⇒ (1 2 3 4 5 6) |
|
|
(-snoc '(1 2 3) '(4 5 6)) |
|
|
⇒ (1 2 3 (4 5 6)) |
|
|
|
|
|
-- Function: -interpose (sep list) |
|
|
Return a new list of all elements in LIST separated by SEP. |
|
|
|
|
|
(-interpose "-" ()) |
|
|
⇒ () |
|
|
(-interpose "-" '("a")) |
|
|
⇒ ("a") |
|
|
(-interpose "-" '("a" "b" "c")) |
|
|
⇒ ("a" "-" "b" "-" "c") |
|
|
|
|
|
-- Function: -interleave (&rest lists) |
|
|
Return a new list of the first item in each list, then the second |
|
|
etc. |
|
|
|
|
|
(-interleave '(1 2) '("a" "b")) |
|
|
⇒ (1 "a" 2 "b") |
|
|
(-interleave '(1 2) '("a" "b") '("A" "B")) |
|
|
⇒ (1 "a" "A" 2 "b" "B") |
|
|
(-interleave '(1 2 3) '("a" "b")) |
|
|
⇒ (1 "a" 2 "b") |
|
|
|
|
|
-- Function: -iota (count &optional start step) |
|
|
Return a list containing COUNT numbers. Starts from START and adds |
|
|
STEP each time. The default START is zero, the default STEP is 1. |
|
|
This function takes its name from the corresponding primitive in |
|
|
the APL language. |
|
|
|
|
|
(-iota 6) |
|
|
⇒ (0 1 2 3 4 5) |
|
|
(-iota 4 2.5 -2) |
|
|
⇒ (2.5 0.5 -1.5 -3.5) |
|
|
(-iota -1) |
|
|
error→ Wrong type argument: natnump, -1 |
|
|
|
|
|
-- Function: -zip-with (fn list1 list2) |
|
|
Zip the two lists LIST1 and LIST2 using a function FN. This |
|
|
function is applied pairwise taking as first argument element of |
|
|
LIST1 and as second argument element of LIST2 at corresponding |
|
|
position. |
|
|
|
|
|
The anaphoric form ‘--zip-with’ binds the elements from LIST1 as |
|
|
symbol ‘it’, and the elements from LIST2 as symbol ‘other’. |
|
|
|
|
|
(-zip-with '+ '(1 2 3) '(4 5 6)) |
|
|
⇒ (5 7 9) |
|
|
(-zip-with 'cons '(1 2 3) '(4 5 6)) |
|
|
⇒ ((1 . 4) (2 . 5) (3 . 6)) |
|
|
(--zip-with (concat it " and " other) '("Batman" "Jekyll") '("Robin" "Hyde")) |
|
|
⇒ ("Batman and Robin" "Jekyll and Hyde") |
|
|
|
|
|
-- Function: -zip (&rest lists) |
|
|
Zip LISTS together. Group the head of each list, followed by the |
|
|
second elements of each list, and so on. The lengths of the |
|
|
returned groupings are equal to the length of the shortest input |
|
|
list. |
|
|
|
|
|
If two lists are provided as arguments, return the groupings as a |
|
|
list of cons cells. Otherwise, return the groupings as a list of |
|
|
lists. |
|
|
|
|
|
Use ‘-zip-lists’ (*note -zip-lists::) if you need the return value |
|
|
to always be a list of lists. |
|
|
|
|
|
Alias: ‘-zip-pair’ |
|
|
|
|
|
See also: ‘-zip-lists’ (*note -zip-lists::) |
|
|
|
|
|
(-zip '(1 2 3) '(4 5 6)) |
|
|
⇒ ((1 . 4) (2 . 5) (3 . 6)) |
|
|
(-zip '(1 2 3) '(4 5 6 7)) |
|
|
⇒ ((1 . 4) (2 . 5) (3 . 6)) |
|
|
(-zip '(1 2) '(3 4 5) '(6)) |
|
|
⇒ ((1 3 6)) |
|
|
|
|
|
-- Function: -zip-lists (&rest lists) |
|
|
Zip LISTS together. Group the head of each list, followed by the |
|
|
second elements of each list, and so on. The lengths of the |
|
|
returned groupings are equal to the length of the shortest input |
|
|
list. |
|
|
|
|
|
The return value is always list of lists, which is a difference |
|
|
from ‘-zip-pair’ which returns a cons-cell in case two input lists |
|
|
are provided. |
|
|
|
|
|
See also: ‘-zip’ (*note -zip::) |
|
|
|
|
|
(-zip-lists '(1 2 3) '(4 5 6)) |
|
|
⇒ ((1 4) (2 5) (3 6)) |
|
|
(-zip-lists '(1 2 3) '(4 5 6 7)) |
|
|
⇒ ((1 4) (2 5) (3 6)) |
|
|
(-zip-lists '(1 2) '(3 4 5) '(6)) |
|
|
⇒ ((1 3 6)) |
|
|
|
|
|
-- Function: -zip-fill (fill-value &rest lists) |
|
|
Zip LISTS, with FILL-VALUE padded onto the shorter lists. The |
|
|
lengths of the returned groupings are equal to the length of the |
|
|
longest input list. |
|
|
|
|
|
(-zip-fill 0 '(1 2 3 4 5) '(6 7 8 9)) |
|
|
⇒ ((1 . 6) (2 . 7) (3 . 8) (4 . 9) (5 . 0)) |
|
|
|
|
|
-- Function: -unzip (lists) |
|
|
Unzip LISTS. |
|
|
|
|
|
This works just like ‘-zip’ (*note -zip::) but takes a list of |
|
|
lists instead of a variable number of arguments, such that |
|
|
|
|
|
(-unzip (-zip L1 L2 L3 ...)) |
|
|
|
|
|
is identity (given that the lists are the same length). |
|
|
|
|
|
Note in particular that calling this on a list of two lists will |
|
|
return a list of cons-cells such that the above identity works. |
|
|
|
|
|
See also: ‘-zip’ (*note -zip::) |
|
|
|
|
|
(-unzip (-zip '(1 2 3) '(a b c) '("e" "f" "g"))) |
|
|
⇒ ((1 2 3) (a b c) ("e" "f" "g")) |
|
|
(-unzip '((1 2) (3 4) (5 6) (7 8) (9 10))) |
|
|
⇒ ((1 3 5 7 9) (2 4 6 8 10)) |
|
|
(-unzip '((1 2) (3 4))) |
|
|
⇒ ((1 . 3) (2 . 4)) |
|
|
|
|
|
-- Function: -cycle (list) |
|
|
Return an infinite circular copy of LIST. The returned list cycles |
|
|
through the elements of LIST and repeats from the beginning. |
|
|
|
|
|
(-take 5 (-cycle '(1 2 3))) |
|
|
⇒ (1 2 3 1 2) |
|
|
(-take 7 (-cycle '(1 "and" 3))) |
|
|
⇒ (1 "and" 3 1 "and" 3 1) |
|
|
(-zip (-cycle '(1 2 3)) '(1 2)) |
|
|
⇒ ((1 . 1) (2 . 2)) |
|
|
|
|
|
-- Function: -pad (fill-value &rest lists) |
|
|
Appends FILL-VALUE to the end of each list in LISTS such that they |
|
|
will all have the same length. |
|
|
|
|
|
(-pad 0 ()) |
|
|
⇒ (nil) |
|
|
(-pad 0 '(1)) |
|
|
⇒ ((1)) |
|
|
(-pad 0 '(1 2 3) '(4 5)) |
|
|
⇒ ((1 2 3) (4 5 0)) |
|
|
|
|
|
-- Function: -table (fn &rest lists) |
|
|
Compute outer product of LISTS using function FN. |
|
|
|
|
|
The function FN should have the same arity as the number of |
|
|
supplied lists. |
|
|
|
|
|
The outer product is computed by applying fn to all possible |
|
|
combinations created by taking one element from each list in order. |
|
|
The dimension of the result is (length lists). |
|
|
|
|
|
See also: ‘-table-flat’ (*note -table-flat::) |
|
|
|
|
|
(-table '* '(1 2 3) '(1 2 3)) |
|
|
⇒ ((1 2 3) (2 4 6) (3 6 9)) |
|
|
(-table (lambda (a b) (-sum (-zip-with '* a b))) '((1 2) (3 4)) '((1 3) (2 4))) |
|
|
⇒ ((7 15) (10 22)) |
|
|
(apply '-table 'list (-repeat 3 '(1 2))) |
|
|
⇒ ((((1 1 1) (2 1 1)) ((1 2 1) (2 2 1))) (((1 1 2) (2 1 2)) ((1 2 2) (2 2 2)))) |
|
|
|
|
|
-- Function: -table-flat (fn &rest lists) |
|
|
Compute flat outer product of LISTS using function FN. |
|
|
|
|
|
The function FN should have the same arity as the number of |
|
|
supplied lists. |
|
|
|
|
|
The outer product is computed by applying fn to all possible |
|
|
combinations created by taking one element from each list in order. |
|
|
The results are flattened, ignoring the tensor structure of the |
|
|
result. This is equivalent to calling: |
|
|
|
|
|
(-flatten-n (1- (length lists)) (apply ’-table fn lists)) |
|
|
|
|
|
but the implementation here is much more efficient. |
|
|
|
|
|
See also: ‘-flatten-n’ (*note -flatten-n::), ‘-table’ (*note |
|
|
-table::) |
|
|
|
|
|
(-table-flat 'list '(1 2 3) '(a b c)) |
|
|
⇒ ((1 a) (2 a) (3 a) (1 b) (2 b) (3 b) (1 c) (2 c) (3 c)) |
|
|
(-table-flat '* '(1 2 3) '(1 2 3)) |
|
|
⇒ (1 2 3 2 4 6 3 6 9) |
|
|
(apply '-table-flat 'list (-repeat 3 '(1 2))) |
|
|
⇒ ((1 1 1) (2 1 1) (1 2 1) (2 2 1) (1 1 2) (2 1 2) (1 2 2) (2 2 2)) |
|
|
|
|
|
-- Function: -first (pred list) |
|
|
Return the first item in LIST for which PRED returns non-‘nil’. |
|
|
Return ‘nil’ if no such element is found. To get the first item in |
|
|
the list no questions asked, use ‘car’. |
|
|
|
|
|
Alias: ‘-find’. |
|
|
|
|
|
This function’s anaphoric counterpart is ‘--first’. |
|
|
|
|
|
(-first #'natnump '(-1 0 1)) |
|
|
⇒ 0 |
|
|
(-first #'null '(1 2 3)) |
|
|
⇒ nil |
|
|
(--first (> it 2) '(1 2 3)) |
|
|
⇒ 3 |
|
|
|
|
|
-- Function: -last (pred list) |
|
|
Return the last x in LIST where (PRED x) is non-‘nil’, else ‘nil’. |
|
|
|
|
|
(-last 'even? '(1 2 3 4 5 6 3 3 3)) |
|
|
⇒ 6 |
|
|
(-last 'even? '(1 3 7 5 9)) |
|
|
⇒ nil |
|
|
(--last (> (length it) 3) '("a" "looong" "word" "and" "short" "one")) |
|
|
⇒ "short" |
|
|
|
|
|
-- Function: -first-item (list) |
|
|
Return the first item of LIST, or ‘nil’ on an empty list. |
|
|
|
|
|
See also: ‘-second-item’ (*note -second-item::), ‘-last-item’ |
|
|
(*note -last-item::). |
|
|
|
|
|
(-first-item '(1 2 3)) |
|
|
⇒ 1 |
|
|
(-first-item nil) |
|
|
⇒ nil |
|
|
(let ((list (list 1 2 3))) (setf (-first-item list) 5) list) |
|
|
⇒ (5 2 3) |
|
|
|
|
|
-- Function: -second-item (list) |
|
|
Return the second item of LIST, or ‘nil’ if LIST is too short. |
|
|
|
|
|
See also: ‘-third-item’ (*note -third-item::). |
|
|
|
|
|
(-second-item '(1 2 3)) |
|
|
⇒ 2 |
|
|
(-second-item nil) |
|
|
⇒ nil |
|
|
|
|
|
-- Function: -third-item (list) |
|
|
Return the third item of LIST, or ‘nil’ if LIST is too short. |
|
|
|
|
|
See also: ‘-fourth-item’ (*note -fourth-item::). |
|
|
|
|
|
(-third-item '(1 2 3)) |
|
|
⇒ 3 |
|
|
(-third-item nil) |
|
|
⇒ nil |
|
|
|
|
|
-- Function: -fourth-item (list) |
|
|
Return the fourth item of LIST, or ‘nil’ if LIST is too short. |
|
|
|
|
|
See also: ‘-fifth-item’ (*note -fifth-item::). |
|
|
|
|
|
(-fourth-item '(1 2 3 4)) |
|
|
⇒ 4 |
|
|
(-fourth-item nil) |
|
|
⇒ nil |
|
|
|
|
|
-- Function: -fifth-item (list) |
|
|
Return the fifth item of LIST, or ‘nil’ if LIST is too short. |
|
|
|
|
|
See also: ‘-last-item’ (*note -last-item::). |
|
|
|
|
|
(-fifth-item '(1 2 3 4 5)) |
|
|
⇒ 5 |
|
|
(-fifth-item nil) |
|
|
⇒ nil |
|
|
|
|
|
-- Function: -last-item (list) |
|
|
Return the last item of LIST, or ‘nil’ on an empty list. |
|
|
|
|
|
(-last-item '(1 2 3)) |
|
|
⇒ 3 |
|
|
(-last-item nil) |
|
|
⇒ nil |
|
|
(let ((list (list 1 2 3))) (setf (-last-item list) 5) list) |
|
|
⇒ (1 2 5) |
|
|
|
|
|
-- Function: -butlast (list) |
|
|
Return a list of all items in list except for the last. |
|
|
|
|
|
(-butlast '(1 2 3)) |
|
|
⇒ (1 2) |
|
|
(-butlast '(1 2)) |
|
|
⇒ (1) |
|
|
(-butlast '(1)) |
|
|
⇒ nil |
|
|
|
|
|
-- Function: -sort (comparator list) |
|
|
Sort LIST, stably, comparing elements using COMPARATOR. Return the |
|
|
sorted list. LIST is NOT modified by side effects. COMPARATOR is |
|
|
called with two elements of LIST, and should return non-‘nil’ if |
|
|
the first element should sort before the second. |
|
|
|
|
|
(-sort '< '(3 1 2)) |
|
|
⇒ (1 2 3) |
|
|
(-sort '> '(3 1 2)) |
|
|
⇒ (3 2 1) |
|
|
(--sort (< it other) '(3 1 2)) |
|
|
⇒ (1 2 3) |
|
|
|
|
|
-- Function: -list (arg) |
|
|
Ensure ARG is a list. If ARG is already a list, return it as is |
|
|
(not a copy). Otherwise, return a new list with ARG as its only |
|
|
element. |
|
|
|
|
|
Another supported calling convention is (-list &rest ARGS). In |
|
|
this case, if ARG is not a list, a new list with all of ARGS as |
|
|
elements is returned. This use is supported for backward |
|
|
compatibility and is otherwise deprecated. |
|
|
|
|
|
(-list 1) |
|
|
⇒ (1) |
|
|
(-list ()) |
|
|
⇒ () |
|
|
(-list '(1 2 3)) |
|
|
⇒ (1 2 3) |
|
|
|
|
|
-- Function: -fix (fn list) |
|
|
Compute the (least) fixpoint of FN with initial input LIST. |
|
|
|
|
|
FN is called at least once, results are compared with ‘equal’. |
|
|
|
|
|
(-fix (lambda (l) (-non-nil (--mapcat (-split-at (/ (length it) 2) it) l))) '((1 2 3))) |
|
|
⇒ ((1) (2) (3)) |
|
|
(let ((l '((starwars scifi) (jedi starwars warrior)))) (--fix (-uniq (--mapcat (cons it (cdr (assq it l))) it)) '(jedi book))) |
|
|
⇒ (jedi starwars warrior scifi book) |
|
|
|
|
|
|
|
|
File: dash.info, Node: Tree operations, Next: Threading macros, Prev: Other list operations, Up: Functions |
|
|
|
|
|
2.11 Tree operations |
|
|
==================== |
|
|
|
|
|
Functions pretending lists are trees. |
|
|
|
|
|
-- Function: -tree-seq (branch children tree) |
|
|
Return a sequence of the nodes in TREE, in depth-first search |
|
|
order. |
|
|
|
|
|
BRANCH is a predicate of one argument that returns non-‘nil’ if the |
|
|
passed argument is a branch, that is, a node that can have |
|
|
children. |
|
|
|
|
|
CHILDREN is a function of one argument that returns the children of |
|
|
the passed branch node. |
|
|
|
|
|
Non-branch nodes are simply copied. |
|
|
|
|
|
(-tree-seq 'listp 'identity '(1 (2 3) 4 (5 (6 7)))) |
|
|
⇒ ((1 (2 3) 4 (5 (6 7))) 1 (2 3) 2 3 4 (5 (6 7)) 5 (6 7) 6 7) |
|
|
(-tree-seq 'listp 'reverse '(1 (2 3) 4 (5 (6 7)))) |
|
|
⇒ ((1 (2 3) 4 (5 (6 7))) (5 (6 7)) (6 7) 7 6 5 4 (2 3) 3 2 1) |
|
|
(--tree-seq (vectorp it) (append it nil) [1 [2 3] 4 [5 [6 7]]]) |
|
|
⇒ ([1 [2 3] 4 [5 [6 7]]] 1 [2 3] 2 3 4 [5 [6 7]] 5 [6 7] 6 7) |
|
|
|
|
|
-- Function: -tree-map (fn tree) |
|
|
Apply FN to each element of TREE while preserving the tree |
|
|
structure. |
|
|
|
|
|
(-tree-map '1+ '(1 (2 3) (4 (5 6) 7))) |
|
|
⇒ (2 (3 4) (5 (6 7) 8)) |
|
|
(-tree-map '(lambda (x) (cons x (expt 2 x))) '(1 (2 3) 4)) |
|
|
⇒ ((1 . 2) ((2 . 4) (3 . 8)) (4 . 16)) |
|
|
(--tree-map (length it) '("<body>" ("<p>" "text" "</p>") "</body>")) |
|
|
⇒ (6 (3 4 4) 7) |
|
|
|
|
|
-- Function: -tree-map-nodes (pred fun tree) |
|
|
Call FUN on each node of TREE that satisfies PRED. |
|
|
|
|
|
If PRED returns ‘nil’, continue descending down this node. If PRED |
|
|
returns non-‘nil’, apply FUN to this node and do not descend |
|
|
further. |
|
|
|
|
|
(-tree-map-nodes 'vectorp (lambda (x) (-sum (append x nil))) '(1 [2 3] 4 (5 [6 7] 8))) |
|
|
⇒ (1 5 4 (5 13 8)) |
|
|
(-tree-map-nodes 'keywordp (lambda (x) (symbol-name x)) '(1 :foo 4 ((5 6 :bar) :baz 8))) |
|
|
⇒ (1 ":foo" 4 ((5 6 ":bar") ":baz" 8)) |
|
|
(--tree-map-nodes (eq (car-safe it) 'add-mode) (-concat it (list :mode 'emacs-lisp-mode)) '(with-mode emacs-lisp-mode (foo bar) (add-mode a b) (baz (add-mode c d)))) |
|
|
⇒ (with-mode emacs-lisp-mode (foo bar) (add-mode a b :mode emacs-lisp-mode) (baz (add-mode c d :mode emacs-lisp-mode))) |
|
|
|
|
|
-- Function: -tree-reduce (fn tree) |
|
|
Use FN to reduce elements of list TREE. If elements of TREE are |
|
|
lists themselves, apply the reduction recursively. |
|
|
|
|
|
FN is first applied to first element of the list and second |
|
|
element, then on this result and third element from the list etc. |
|
|
|
|
|
See ‘-reduce-r’ (*note -reduce-r::) for how exactly are lists of |
|
|
zero or one element handled. |
|
|
|
|
|
(-tree-reduce '+ '(1 (2 3) (4 5))) |
|
|
⇒ 15 |
|
|
(-tree-reduce 'concat '("strings" (" on" " various") ((" levels")))) |
|
|
⇒ "strings on various levels" |
|
|
(--tree-reduce (cond ((stringp it) (concat it " " acc)) (t (let ((sn (symbol-name it))) (concat "<" sn ">" acc "</" sn ">")))) '(body (p "some words") (div "more" (b "bold") "words"))) |
|
|
⇒ "<body><p>some words</p> <div>more <b>bold</b> words</div></body>" |
|
|
|
|
|
-- Function: -tree-reduce-from (fn init-value tree) |
|
|
Use FN to reduce elements of list TREE. If elements of TREE are |
|
|
lists themselves, apply the reduction recursively. |
|
|
|
|
|
FN is first applied to INIT-VALUE and first element of the list, |
|
|
then on this result and second element from the list etc. |
|
|
|
|
|
The initial value is ignored on cons pairs as they always contain |
|
|
two elements. |
|
|
|
|
|
(-tree-reduce-from '+ 1 '(1 (1 1) ((1)))) |
|
|
⇒ 8 |
|
|
(--tree-reduce-from (-concat acc (list it)) nil '(1 (2 3 (4 5)) (6 7))) |
|
|
⇒ ((7 6) ((5 4) 3 2) 1) |
|
|
|
|
|
-- Function: -tree-mapreduce (fn folder tree) |
|
|
Apply FN to each element of TREE, and make a list of the results. |
|
|
If elements of TREE are lists themselves, apply FN recursively to |
|
|
elements of these nested lists. |
|
|
|
|
|
Then reduce the resulting lists using FOLDER and initial value |
|
|
INIT-VALUE. See ‘-reduce-r-from’ (*note -reduce-r-from::). |
|
|
|
|
|
This is the same as calling ‘-tree-reduce’ (*note -tree-reduce::) |
|
|
after ‘-tree-map’ (*note -tree-map::) but is twice as fast as it |
|
|
only traverse the structure once. |
|
|
|
|
|
(-tree-mapreduce 'list 'append '(1 (2 (3 4) (5 6)) (7 (8 9)))) |
|
|
⇒ (1 2 3 4 5 6 7 8 9) |
|
|
(--tree-mapreduce 1 (+ it acc) '(1 (2 (4 9) (2 1)) (7 (4 3)))) |
|
|
⇒ 9 |
|
|
(--tree-mapreduce 0 (max acc (1+ it)) '(1 (2 (4 9) (2 1)) (7 (4 3)))) |
|
|
⇒ 3 |
|
|
|
|
|
-- Function: -tree-mapreduce-from (fn folder init-value tree) |
|
|
Apply FN to each element of TREE, and make a list of the results. |
|
|
If elements of TREE are lists themselves, apply FN recursively to |
|
|
elements of these nested lists. |
|
|
|
|
|
Then reduce the resulting lists using FOLDER and initial value |
|
|
INIT-VALUE. See ‘-reduce-r-from’ (*note -reduce-r-from::). |
|
|
|
|
|
This is the same as calling ‘-tree-reduce-from’ (*note |
|
|
-tree-reduce-from::) after ‘-tree-map’ (*note -tree-map::) but is |
|
|
twice as fast as it only traverse the structure once. |
|
|
|
|
|
(-tree-mapreduce-from 'identity '* 1 '(1 (2 (3 4) (5 6)) (7 (8 9)))) |
|
|
⇒ 362880 |
|
|
(--tree-mapreduce-from (+ it it) (cons it acc) nil '(1 (2 (4 9) (2 1)) (7 (4 3)))) |
|
|
⇒ (2 (4 (8 18) (4 2)) (14 (8 6))) |
|
|
(concat "{" (--tree-mapreduce-from (cond ((-cons-pair? it) (concat (symbol-name (car it)) " -> " (symbol-name (cdr it)))) (t (concat (symbol-name it) " : {"))) (concat it (unless (or (equal acc "}") (equal (substring it (1- (length it))) "{")) ", ") acc) "}" '((elisp-mode (foo (bar . booze)) (baz . qux)) (c-mode (foo . bla) (bum . bam))))) |
|
|
⇒ "{elisp-mode : {foo : {bar -> booze}, baz -> qux}, c-mode : {foo -> bla, bum -> bam}}" |
|
|
|
|
|
-- Function: -clone (list) |
|
|
Create a deep copy of LIST. The new list has the same elements and |
|
|
structure but all cons are replaced with new ones. This is useful |
|
|
when you need to clone a structure such as plist or alist. |
|
|
|
|
|
(let* ((a '(1 2 3)) (b (-clone a))) (nreverse a) b) |
|
|
⇒ (1 2 3) |
|
|
|
|
|
|
|
|
File: dash.info, Node: Threading macros, Next: Binding, Prev: Tree operations, Up: Functions |
|
|
|
|
|
2.12 Threading macros |
|
|
===================== |
|
|
|
|
|
Macros that conditionally combine sequential forms for brevity or |
|
|
readability. |
|
|
|
|
|
-- Macro: -> (x &optional form &rest more) |
|
|
Thread the expr through the forms. Insert X as the second item in |
|
|
the first form, making a list of it if it is not a list already. |
|
|
If there are more forms, insert the first form as the second item |
|
|
in second form, etc. |
|
|
|
|
|
(-> '(2 3 5)) |
|
|
⇒ (2 3 5) |
|
|
(-> '(2 3 5) (append '(8 13))) |
|
|
⇒ (2 3 5 8 13) |
|
|
(-> '(2 3 5) (append '(8 13)) (-slice 1 -1)) |
|
|
⇒ (3 5 8) |
|
|
|
|
|
-- Macro: ->> (x &optional form &rest more) |
|
|
Thread the expr through the forms. Insert X as the last item in |
|
|
the first form, making a list of it if it is not a list already. |
|
|
If there are more forms, insert the first form as the last item in |
|
|
second form, etc. |
|
|
|
|
|
(->> '(1 2 3) (-map 'square)) |
|
|
⇒ (1 4 9) |
|
|
(->> '(1 2 3) (-map 'square) (-remove 'even?)) |
|
|
⇒ (1 9) |
|
|
(->> '(1 2 3) (-map 'square) (-reduce '+)) |
|
|
⇒ 14 |
|
|
|
|
|
-- Macro: --> (x &rest forms) |
|
|
Starting with the value of X, thread each expression through FORMS. |
|
|
|
|
|
Insert X at the position signified by the symbol ‘it’ in the first |
|
|
form. If there are more forms, insert the first form at the |
|
|
position signified by ‘it’ in in second form, etc. |
|
|
|
|
|
(--> "def" (concat "abc" it "ghi")) |
|
|
⇒ "abcdefghi" |
|
|
(--> "def" (concat "abc" it "ghi") (upcase it)) |
|
|
⇒ "ABCDEFGHI" |
|
|
(--> "def" (concat "abc" it "ghi") upcase) |
|
|
⇒ "ABCDEFGHI" |
|
|
|
|
|
-- Macro: -as-> (value variable &rest forms) |
|
|
Starting with VALUE, thread VARIABLE through FORMS. |
|
|
|
|
|
In the first form, bind VARIABLE to VALUE. In the second form, |
|
|
bind VARIABLE to the result of the first form, and so forth. |
|
|
|
|
|
(-as-> 3 my-var (1+ my-var) (list my-var) (mapcar (lambda (ele) (* 2 ele)) my-var)) |
|
|
⇒ (8) |
|
|
(-as-> 3 my-var 1+) |
|
|
⇒ 4 |
|
|
(-as-> 3 my-var) |
|
|
⇒ 3 |
|
|
|
|
|
-- Macro: -some-> (x &optional form &rest more) |
|
|
When expr is non-‘nil’, thread it through the first form (via ‘->’ |
|
|
(*note ->::)), and when that result is non-‘nil’, through the next |
|
|
form, etc. |
|
|
|
|
|
(-some-> '(2 3 5)) |
|
|
⇒ (2 3 5) |
|
|
(-some-> 5 square) |
|
|
⇒ 25 |
|
|
(-some-> 5 even? square) |
|
|
⇒ nil |
|
|
|
|
|
-- Macro: -some->> (x &optional form &rest more) |
|
|
When expr is non-‘nil’, thread it through the first form (via ‘->>’ |
|
|
(*note ->>::)), and when that result is non-‘nil’, through the next |
|
|
form, etc. |
|
|
|
|
|
(-some->> '(1 2 3) (-map 'square)) |
|
|
⇒ (1 4 9) |
|
|
(-some->> '(1 3 5) (-last 'even?) (+ 100)) |
|
|
⇒ nil |
|
|
(-some->> '(2 4 6) (-last 'even?) (+ 100)) |
|
|
⇒ 106 |
|
|
|
|
|
-- Macro: -some--> (expr &rest forms) |
|
|
Thread EXPR through FORMS via ‘-->’ (*note -->::), while the result |
|
|
is non-‘nil’. When EXPR evaluates to non-‘nil’, thread the result |
|
|
through the first of FORMS, and when that result is non-‘nil’, |
|
|
thread it through the next form, etc. |
|
|
|
|
|
(-some--> "def" (concat "abc" it "ghi")) |
|
|
⇒ "abcdefghi" |
|
|
(-some--> nil (concat "abc" it "ghi")) |
|
|
⇒ nil |
|
|
(-some--> '(0 1) (-remove #'natnump it) (append it it) (-map #'1+ it)) |
|
|
⇒ () |
|
|
|
|
|
-- Macro: -doto (init &rest forms) |
|
|
Evaluate INIT and pass it as argument to FORMS with ‘->’ (*note |
|
|
->::). The RESULT of evaluating INIT is threaded through each of |
|
|
FORMS individually using ‘->’ (*note ->::), which see. The return |
|
|
value is RESULT, which FORMS may have modified by side effect. |
|
|
|
|
|
(-doto (list 1 2 3) pop pop) |
|
|
⇒ (3) |
|
|
(-doto (cons 1 2) (setcar 3) (setcdr 4)) |
|
|
⇒ (3 . 4) |
|
|
(gethash 'k (--doto (make-hash-table) (puthash 'k 'v it))) |
|
|
⇒ v |
|
|
|
|
|
|
|
|
File: dash.info, Node: Binding, Next: Side effects, Prev: Threading macros, Up: Functions |
|
|
|
|
|
2.13 Binding |
|
|
============ |
|
|
|
|
|
Macros that combine ‘let’ and ‘let*’ with destructuring and flow |
|
|
control. |
|
|
|
|
|
-- Macro: -when-let ((var val) &rest body) |
|
|
If VAL evaluates to non-‘nil’, bind it to VAR and execute body. |
|
|
|
|
|
Note: binding is done according to ‘-let’ (*note -let::). |
|
|
|
|
|
(-when-let (match-index (string-match "d" "abcd")) (+ match-index 2)) |
|
|
⇒ 5 |
|
|
(-when-let ((&plist :foo foo) (list :foo "foo")) foo) |
|
|
⇒ "foo" |
|
|
(-when-let ((&plist :foo foo) (list :bar "bar")) foo) |
|
|
⇒ nil |
|
|
|
|
|
-- Macro: -when-let* (vars-vals &rest body) |
|
|
If all VALS evaluate to true, bind them to their corresponding VARS |
|
|
and execute body. VARS-VALS should be a list of (VAR VAL) pairs. |
|
|
|
|
|
Note: binding is done according to ‘-let*’ (*note -let*::). VALS |
|
|
are evaluated sequentially, and evaluation stops after the first |
|
|
‘nil’ VAL is encountered. |
|
|
|
|
|
(-when-let* ((x 5) (y 3) (z (+ y 4))) (+ x y z)) |
|
|
⇒ 15 |
|
|
(-when-let* ((x 5) (y nil) (z 7)) (+ x y z)) |
|
|
⇒ nil |
|
|
|
|
|
-- Macro: -if-let ((var val) then &rest else) |
|
|
If VAL evaluates to non-‘nil’, bind it to VAR and do THEN, |
|
|
otherwise do ELSE. |
|
|
|
|
|
Note: binding is done according to ‘-let’ (*note -let::). |
|
|
|
|
|
(-if-let (match-index (string-match "d" "abc")) (+ match-index 3) 7) |
|
|
⇒ 7 |
|
|
(--if-let (even? 4) it nil) |
|
|
⇒ t |
|
|
|
|
|
-- Macro: -if-let* (vars-vals then &rest else) |
|
|
If all VALS evaluate to true, bind them to their corresponding VARS |
|
|
and do THEN, otherwise do ELSE. VARS-VALS should be a list of (VAR |
|
|
VAL) pairs. |
|
|
|
|
|
Note: binding is done according to ‘-let*’ (*note -let*::). VALS |
|
|
are evaluated sequentially, and evaluation stops after the first |
|
|
‘nil’ VAL is encountered. |
|
|
|
|
|
(-if-let* ((x 5) (y 3) (z 7)) (+ x y z) "foo") |
|
|
⇒ 15 |
|
|
(-if-let* ((x 5) (y nil) (z 7)) (+ x y z) "foo") |
|
|
⇒ "foo" |
|
|
(-if-let* (((_ _ x) '(nil nil 7))) x) |
|
|
⇒ 7 |
|
|
|
|
|
-- Macro: -let (varlist &rest body) |
|
|
Bind variables according to VARLIST then eval BODY. |
|
|
|
|
|
VARLIST is a list of lists of the form (PATTERN SOURCE). Each |
|
|
PATTERN is matched against the SOURCE "structurally". SOURCE is |
|
|
only evaluated once for each PATTERN. Each PATTERN is matched |
|
|
recursively, and can therefore contain sub-patterns which are |
|
|
matched against corresponding sub-expressions of SOURCE. |
|
|
|
|
|
All the SOURCEs are evalled before any symbols are bound (i.e. "in |
|
|
parallel"). |
|
|
|
|
|
If VARLIST only contains one (PATTERN SOURCE) element, you can |
|
|
optionally specify it using a vector and discarding the outer-most |
|
|
parens. Thus |
|
|
|
|
|
(-let ((PATTERN SOURCE)) ...) |
|
|
|
|
|
becomes |
|
|
|
|
|
(-let [PATTERN SOURCE] ...). |
|
|
|
|
|
‘-let’ (*note -let::) uses a convention of not binding places |
|
|
(symbols) starting with _ whenever it’s possible. You can use this |
|
|
to skip over entries you don’t care about. However, this is not |
|
|
*always* possible (as a result of implementation) and these symbols |
|
|
might get bound to undefined values. |
|
|
|
|
|
Following is the overview of supported patterns. Remember that |
|
|
patterns can be matched recursively, so every a, b, aK in the |
|
|
following can be a matching construct and not necessarily a |
|
|
symbol/variable. |
|
|
|
|
|
Symbol: |
|
|
|
|
|
a - bind the SOURCE to A. This is just like regular ‘let’. |
|
|
|
|
|
Conses and lists: |
|
|
|
|
|
(a) - bind ‘car’ of cons/list to A |
|
|
|
|
|
(a . b) - bind car of cons to A and ‘cdr’ to B |
|
|
|
|
|
(a b) - bind car of list to A and ‘cadr’ to B |
|
|
|
|
|
(a1 a2 a3 ...) - bind 0th car of list to A1, 1st to A2, 2nd to |
|
|
A3... |
|
|
|
|
|
(a1 a2 a3 ... aN . rest) - as above, but bind the Nth cdr to REST. |
|
|
|
|
|
Vectors: |
|
|
|
|
|
[a] - bind 0th element of a non-list sequence to A (works with |
|
|
vectors, strings, bit arrays...) |
|
|
|
|
|
[a1 a2 a3 ...] - bind 0th element of non-list sequence to A0, 1st |
|
|
to A1, 2nd to A2, ... If the PATTERN is shorter than SOURCE, the |
|
|
values at places not in PATTERN are ignored. If the PATTERN is |
|
|
longer than SOURCE, an ‘error’ is thrown. |
|
|
|
|
|
[a1 a2 a3 ... &rest rest] - as above, but bind the rest of the |
|
|
sequence to REST. This is conceptually the same as improper list |
|
|
matching (a1 a2 ... aN . rest) |
|
|
|
|
|
Key/value stores: |
|
|
|
|
|
(&plist key0 a0 ... keyN aN) - bind value mapped by keyK in the |
|
|
SOURCE plist to aK. If the value is not found, aK is ‘nil’. Uses |
|
|
‘plist-get’ to fetch values. |
|
|
|
|
|
(&alist key0 a0 ... keyN aN) - bind value mapped by keyK in the |
|
|
SOURCE alist to aK. If the value is not found, aK is ‘nil’. Uses |
|
|
‘assoc’ to fetch values. |
|
|
|
|
|
(&hash key0 a0 ... keyN aN) - bind value mapped by keyK in the |
|
|
SOURCE hash table to aK. If the value is not found, aK is ‘nil’. |
|
|
Uses ‘gethash’ to fetch values. |
|
|
|
|
|
Further, special keyword &keys supports "inline" matching of |
|
|
plist-like key-value pairs, similarly to &keys keyword of |
|
|
‘cl-defun’. |
|
|
|
|
|
(a1 a2 ... aN &keys key1 b1 ... keyN bK) |
|
|
|
|
|
This binds N values from the list to a1 ... aN, then interprets the |
|
|
cdr as a plist (see key/value matching above). |
|
|
|
|
|
A shorthand notation for kv-destructuring exists which allows the |
|
|
patterns be optionally left out and derived from the key name in |
|
|
the following fashion: |
|
|
|
|
|
- a key :foo is converted into ‘foo’ pattern, - a key ’bar is |
|
|
converted into ‘bar’ pattern, - a key "baz" is converted into ‘baz’ |
|
|
pattern. |
|
|
|
|
|
That is, the entire value under the key is bound to the derived |
|
|
variable without any further destructuring. |
|
|
|
|
|
This is possible only when the form following the key is not a |
|
|
valid pattern (i.e. not a symbol, a cons cell or a vector). |
|
|
Otherwise the matching proceeds as usual and in case of an invalid |
|
|
spec fails with an error. |
|
|
|
|
|
Thus the patterns are normalized as follows: |
|
|
|
|
|
;; derive all the missing patterns (&plist :foo ’bar "baz") => |
|
|
(&plist :foo foo ’bar bar "baz" baz) |
|
|
|
|
|
;; we can specify some but not others (&plist :foo ’bar |
|
|
explicit-bar) => (&plist :foo foo ’bar explicit-bar) |
|
|
|
|
|
;; nothing happens, we store :foo in x (&plist :foo x) => (&plist |
|
|
:foo x) |
|
|
|
|
|
;; nothing happens, we match recursively (&plist :foo (a b c)) => |
|
|
(&plist :foo (a b c)) |
|
|
|
|
|
You can name the source using the syntax SYMBOL &as PATTERN. This |
|
|
syntax works with lists (proper or improper), vectors and all types |
|
|
of maps. |
|
|
|
|
|
(list &as a b c) (list 1 2 3) |
|
|
|
|
|
binds A to 1, B to 2, C to 3 and LIST to (1 2 3). |
|
|
|
|
|
Similarly: |
|
|
|
|
|
(bounds &as beg . end) (cons 1 2) |
|
|
|
|
|
binds BEG to 1, END to 2 and BOUNDS to (1 . 2). |
|
|
|
|
|
(items &as first . rest) (list 1 2 3) |
|
|
|
|
|
binds FIRST to 1, REST to (2 3) and ITEMS to (1 2 3) |
|
|
|
|
|
[vect &as _ b c] [1 2 3] |
|
|
|
|
|
binds B to 2, C to 3 and VECT to [1 2 3] (_ avoids binding as |
|
|
usual). |
|
|
|
|
|
(plist &as &plist :b b) (list :a 1 :b 2 :c 3) |
|
|
|
|
|
binds B to 2 and PLIST to (:a 1 :b 2 :c 3). Same for &alist and |
|
|
&hash. |
|
|
|
|
|
This is especially useful when we want to capture the result of a |
|
|
computation and destructure at the same time. Consider the form |
|
|
(function-returning-complex-structure) returning a list of two |
|
|
vectors with two items each. We want to capture this entire result |
|
|
and pass it to another computation, but at the same time we want to |
|
|
get the second item from each vector. We can achieve it with |
|
|
pattern |
|
|
|
|
|
(result &as [_ a] [_ b]) (function-returning-complex-structure) |
|
|
|
|
|
Note: Clojure programmers may know this feature as the ":as |
|
|
binding". The difference is that we put the &as at the front |
|
|
because we need to support improper list binding. |
|
|
|
|
|
(-let (([a (b c) d] [1 (2 3) 4])) (list a b c d)) |
|
|
⇒ (1 2 3 4) |
|
|
(-let [(a b c . d) (list 1 2 3 4 5 6)] (list a b c d)) |
|
|
⇒ (1 2 3 (4 5 6)) |
|
|
(-let [(&plist :foo foo :bar bar) (list :baz 3 :foo 1 :qux 4 :bar 2)] (list foo bar)) |
|
|
⇒ (1 2) |
|
|
|
|
|
-- Macro: -let* (varlist &rest body) |
|
|
Bind variables according to VARLIST then eval BODY. |
|
|
|
|
|
VARLIST is a list of lists of the form (PATTERN SOURCE). Each |
|
|
PATTERN is matched against the SOURCE structurally. SOURCE is only |
|
|
evaluated once for each PATTERN. |
|
|
|
|
|
Each SOURCE can refer to the symbols already bound by this VARLIST. |
|
|
This is useful if you want to destructure SOURCE recursively but |
|
|
also want to name the intermediate structures. |
|
|
|
|
|
See ‘-let’ (*note -let::) for the list of all possible patterns. |
|
|
|
|
|
(-let* (((a . b) (cons 1 2)) ((c . d) (cons 3 4))) (list a b c d)) |
|
|
⇒ (1 2 3 4) |
|
|
(-let* (((a . b) (cons 1 (cons 2 3))) ((c . d) b)) (list a b c d)) |
|
|
⇒ (1 (2 . 3) 2 3) |
|
|
(-let* (((&alist "foo" foo "bar" bar) (list (cons "foo" 1) (cons "bar" (list 'a 'b 'c)))) ((a b c) bar)) (list foo a b c bar)) |
|
|
⇒ (1 a b c (a b c)) |
|
|
|
|
|
-- Macro: -lambda (match-form &rest body) |
|
|
Return a lambda which destructures its input as MATCH-FORM and |
|
|
executes BODY. |
|
|
|
|
|
Note that you have to enclose the MATCH-FORM in a pair of parens, |
|
|
such that: |
|
|
|
|
|
(-lambda (x) body) (-lambda (x y ...) body) |
|
|
|
|
|
has the usual semantics of ‘lambda’. Furthermore, these get |
|
|
translated into normal ‘lambda’, so there is no performance |
|
|
penalty. |
|
|
|
|
|
See ‘-let’ (*note -let::) for a description of the destructuring |
|
|
mechanism. |
|
|
|
|
|
(-map (-lambda ((x y)) (+ x y)) '((1 2) (3 4) (5 6))) |
|
|
⇒ (3 7 11) |
|
|
(-map (-lambda ([x y]) (+ x y)) '([1 2] [3 4] [5 6])) |
|
|
⇒ (3 7 11) |
|
|
(funcall (-lambda ((_ . a) (_ . b)) (-concat a b)) '(1 2 3) '(4 5 6)) |
|
|
⇒ (2 3 5 6) |
|
|
|
|
|
-- Macro: -setq ([match-form val] ...) |
|
|
Bind each MATCH-FORM to the value of its VAL. |
|
|
|
|
|
MATCH-FORM destructuring is done according to the rules of ‘-let’ |
|
|
(*note -let::). |
|
|
|
|
|
This macro allows you to bind multiple variables by destructuring |
|
|
the value, so for example: |
|
|
|
|
|
(-setq (a b) x (&plist :c c) plist) |
|
|
|
|
|
expands roughly speaking to the following code |
|
|
|
|
|
(setq a (car x) b (cadr x) c (plist-get plist :c)) |
|
|
|
|
|
Care is taken to only evaluate each VAL once so that in case of |
|
|
multiple assignments it does not cause unexpected side effects. |
|
|
|
|
|
(let (a) (-setq a 1) a) |
|
|
⇒ 1 |
|
|
(let (a b) (-setq (a b) (list 1 2)) (list a b)) |
|
|
⇒ (1 2) |
|
|
(let (c) (-setq (&plist :c c) (list :c "c")) c) |
|
|
⇒ "c" |
|
|
|
|
|
|
|
|
File: dash.info, Node: Side effects, Next: Destructive operations, Prev: Binding, Up: Functions |
|
|
|
|
|
2.14 Side effects |
|
|
================= |
|
|
|
|
|
Functions iterating over lists for side effect only. |
|
|
|
|
|
-- Function: -each (list fn) |
|
|
Call FN on each element of LIST. Return ‘nil’; this function is |
|
|
intended for side effects. |
|
|
|
|
|
Its anaphoric counterpart is ‘--each’. |
|
|
|
|
|
For access to the current element’s index in LIST, see |
|
|
‘-each-indexed’ (*note -each-indexed::). |
|
|
|
|
|
(let (l) (-each '(1 2 3) (lambda (x) (push x l))) l) |
|
|
⇒ (3 2 1) |
|
|
(let (l) (--each '(1 2 3) (push it l)) l) |
|
|
⇒ (3 2 1) |
|
|
(-each '(1 2 3) #'identity) |
|
|
⇒ nil |
|
|
|
|
|
-- Function: -each-while (list pred fn) |
|
|
Call FN on each ITEM in LIST, while (PRED ITEM) is non-‘nil’. Once |
|
|
an ITEM is reached for which PRED returns ‘nil’, FN is no longer |
|
|
called. Return ‘nil’; this function is intended for side effects. |
|
|
|
|
|
Its anaphoric counterpart is ‘--each-while’. |
|
|
|
|
|
(let (l) (-each-while '(2 4 5 6) #'even? (lambda (x) (push x l))) l) |
|
|
⇒ (4 2) |
|
|
(let (l) (--each-while '(1 2 3 4) (< it 3) (push it l)) l) |
|
|
⇒ (2 1) |
|
|
(let ((s 0)) (--each-while '(1 3 4 5) (< it 5) (setq s (+ s it))) s) |
|
|
⇒ 8 |
|
|
|
|
|
-- Function: -each-indexed (list fn) |
|
|
Call FN on each index and element of LIST. For each ITEM at INDEX |
|
|
in LIST, call (funcall FN INDEX ITEM). Return ‘nil’; this function |
|
|
is intended for side effects. |
|
|
|
|
|
See also: ‘-map-indexed’ (*note -map-indexed::). |
|
|
|
|
|
(let (l) (-each-indexed '(a b c) (lambda (i x) (push (list x i) l))) l) |
|
|
⇒ ((c 2) (b 1) (a 0)) |
|
|
(let (l) (--each-indexed '(a b c) (push (list it it-index) l)) l) |
|
|
⇒ ((c 2) (b 1) (a 0)) |
|
|
(let (l) (--each-indexed () (push it l)) l) |
|
|
⇒ () |
|
|
|
|
|
-- Function: -each-r (list fn) |
|
|
Call FN on each element of LIST in reversed order. Return ‘nil’; |
|
|
this function is intended for side effects. |
|
|
|
|
|
Its anaphoric counterpart is ‘--each-r’. |
|
|
|
|
|
(let (l) (-each-r '(1 2 3) (lambda (x) (push x l))) l) |
|
|
⇒ (1 2 3) |
|
|
(let (l) (--each-r '(1 2 3) (push it l)) l) |
|
|
⇒ (1 2 3) |
|
|
(-each-r '(1 2 3) #'identity) |
|
|
⇒ nil |
|
|
|
|
|
-- Function: -each-r-while (list pred fn) |
|
|
Call FN on each ITEM in reversed LIST, while (PRED ITEM) is |
|
|
non-‘nil’. Once an ITEM is reached for which PRED returns ‘nil’, |
|
|
FN is no longer called. Return ‘nil’; this function is intended |
|
|
for side effects. |
|
|
|
|
|
Its anaphoric counterpart is ‘--each-r-while’. |
|
|
|
|
|
(let (l) (-each-r-while '(2 4 5 6) #'even? (lambda (x) (push x l))) l) |
|
|
⇒ (6) |
|
|
(let (l) (--each-r-while '(1 2 3 4) (>= it 3) (push it l)) l) |
|
|
⇒ (3 4) |
|
|
(let ((s 0)) (--each-r-while '(1 2 3 5) (> it 1) (setq s (+ s it))) s) |
|
|
⇒ 10 |
|
|
|
|
|
-- Function: -dotimes (num fn) |
|
|
Call FN NUM times, presumably for side effects. FN is called with |
|
|
a single argument on successive integers running from 0, inclusive, |
|
|
to NUM, exclusive. FN is not called if NUM is less than 1. |
|
|
|
|
|
This function’s anaphoric counterpart is ‘--dotimes’. |
|
|
|
|
|
(let (s) (-dotimes 3 (lambda (n) (push n s))) s) |
|
|
⇒ (2 1 0) |
|
|
(let (s) (-dotimes 0 (lambda (n) (push n s))) s) |
|
|
⇒ () |
|
|
(let (s) (--dotimes 5 (push it s)) s) |
|
|
⇒ (4 3 2 1 0) |
|
|
|
|
|
|
|
|
File: dash.info, Node: Destructive operations, Next: Function combinators, Prev: Side effects, Up: Functions |
|
|
|
|
|
2.15 Destructive operations |
|
|
=========================== |
|
|
|
|
|
Macros that modify variables holding lists. |
|
|
|
|
|
-- Macro: !cons (car cdr) |
|
|
Destructive: Set CDR to the cons of CAR and CDR. |
|
|
|
|
|
(let (l) (!cons 5 l) l) |
|
|
⇒ (5) |
|
|
(let ((l '(3))) (!cons 5 l) l) |
|
|
⇒ (5 3) |
|
|
|
|
|
-- Macro: !cdr (list) |
|
|
Destructive: Set LIST to the cdr of LIST. |
|
|
|
|
|
(let ((l '(3))) (!cdr l) l) |
|
|
⇒ () |
|
|
(let ((l '(3 5))) (!cdr l) l) |
|
|
⇒ (5) |
|
|
|
|
|
|
|
|
File: dash.info, Node: Function combinators, Prev: Destructive operations, Up: Functions |
|
|
|
|
|
2.16 Function combinators |
|
|
========================= |
|
|
|
|
|
Functions that manipulate and compose other functions. |
|
|
|
|
|
-- Function: -partial (fun &rest args) |
|
|
Return a function that is a partial application of FUN to ARGS. |
|
|
ARGS is a list of the first N arguments to pass to FUN. The result |
|
|
is a new function which does the same as FUN, except that the first |
|
|
N arguments are fixed at the values with which this function was |
|
|
called. |
|
|
|
|
|
(funcall (-partial #'+ 5)) |
|
|
⇒ 5 |
|
|
(funcall (-partial #'- 5) 3) |
|
|
⇒ 2 |
|
|
(funcall (-partial #'+ 5 2) 3) |
|
|
⇒ 10 |
|
|
|
|
|
-- Function: -rpartial (fn &rest 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’ (*note -partial::), except the |
|
|
arguments are fixed starting from the right rather than the left. |
|
|
|
|
|
(funcall (-rpartial #'- 5)) |
|
|
⇒ -5 |
|
|
(funcall (-rpartial #'- 5) 8) |
|
|
⇒ 3 |
|
|
(funcall (-rpartial #'- 5 2) 10) |
|
|
⇒ 3 |
|
|
|
|
|
-- Function: -juxt (&rest fns) |
|
|
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. |
|
|
|
|
|
(funcall (-juxt) 1 2) |
|
|
⇒ () |
|
|
(funcall (-juxt #'+ #'- #'* #'/) 7 5) |
|
|
⇒ (12 2 35 1) |
|
|
(mapcar (-juxt #'number-to-string #'1+) '(1 2)) |
|
|
⇒ (("1" 2) ("2" 3)) |
|
|
|
|
|
-- Function: -compose (&rest 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. |
|
|
|
|
|
(funcall (-compose #'- #'1+ #'+) 1 2 3) |
|
|
⇒ -7 |
|
|
(funcall (-compose #'identity #'1+) 3) |
|
|
⇒ 4 |
|
|
(mapcar (-compose #'not #'stringp) '(nil "")) |
|
|
⇒ (t nil) |
|
|
|
|
|
-- Function: -applify (fn) |
|
|
Return a function that applies FN to a single list of args. This |
|
|
changes the arity of FN from taking N distinct arguments to taking |
|
|
1 argument which is a list of N arguments. |
|
|
|
|
|
(funcall (-applify #'+) nil) |
|
|
⇒ 0 |
|
|
(mapcar (-applify #'+) '((1 1 1) (1 2 3) (5 5 5))) |
|
|
⇒ (3 6 15) |
|
|
(funcall (-applify #'<) '(3 6)) |
|
|
⇒ t |
|
|
|
|
|
-- Function: -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. |
|
|
|
|
|
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+)) = (+) |
|
|
|
|
|
(-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) |
|
|
|
|
|
-- Function: -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’ (*note -rotate-args::). |
|
|
|
|
|
(-sort (-flip #'<) '(4 3 6 1)) |
|
|
⇒ (6 4 3 1) |
|
|
(funcall (-flip #'-) 3 2 1 10) |
|
|
⇒ 4 |
|
|
(funcall (-flip #'1+) 1) |
|
|
⇒ 2 |
|
|
|
|
|
-- Function: -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’ (*note -rotate::), and applies FN |
|
|
to the result. |
|
|
|
|
|
See also: ‘-flip’ (*note -flip::). |
|
|
|
|
|
(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) |
|
|
|
|
|
-- Function: -const (c) |
|
|
Return a function that returns C ignoring any additional arguments. |
|
|
|
|
|
In types: a -> b -> a |
|
|
|
|
|
(funcall (-const 2) 1 3 "foo") |
|
|
⇒ 2 |
|
|
(mapcar (-const 1) '("a" "b" "c" "d")) |
|
|
⇒ (1 1 1 1) |
|
|
(-sum (mapcar (-const 1) '("a" "b" "c" "d"))) |
|
|
⇒ 4 |
|
|
|
|
|
-- Macro: -cut (&rest params) |
|
|
Take n-ary function and n arguments and specialize some of them. |
|
|
Arguments denoted by <> will be left unspecialized. |
|
|
|
|
|
See SRFI-26 for detailed description. |
|
|
|
|
|
(funcall (-cut list 1 <> 3 <> 5) 2 4) |
|
|
⇒ (1 2 3 4 5) |
|
|
(-map (-cut funcall <> 5) `(1+ 1- ,(lambda (x) (/ 1.0 x)))) |
|
|
⇒ (6 4 0.2) |
|
|
(-map (-cut <> 1 2 3) '(list vector string)) |
|
|
⇒ ((1 2 3) [1 2 3] "\1\2\3") |
|
|
|
|
|
-- Function: -not (pred) |