\input texinfo @c -*- texinfo -*- @c %**start of header @setfilename dash.info @set DASHVER 2.17.0 @set DASHFNVER 1.2.0 @settitle Dash: A modern list library for GNU Emacs. @documentencoding UTF-8 @documentlanguage en @c %**end of header @copying This manual is for Dash version @value{DASHVER}. Copyright @copyright{} 2012--2021 Free Software Foundation, Inc. @quotation 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''. @end quotation @end copying @dircategory Emacs @direntry * Dash: (dash.info). A modern list library for GNU Emacs. @end direntry @titlepage @title Dash Manual @subtitle For Dash Version @value{DASHVER}. @author Magnar Sveen @page @vskip 0pt plus 1filll @insertcopying @end titlepage @contents @ifnottex @node Top @top Dash @insertcopying @end ifnottex @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. @detailmenu --- 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. 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. * Change log:: List of significant changes by version. * Contributors:: List of contributors. @end detailmenu @end menu @node Installation @chapter Installation Dash is available on @url{https://elpa.gnu.org/, GNU ELPA} and @url{https://melpa.org/, MELPA}, and can be installed with the standard command @code{package-install} (@pxref{Package Installation,,, emacs, The GNU Emacs Manual}). @table @kbd @item M-x package-install @key{RET} dash @key{RET} Install the Dash library. @item M-x package-install @key{RET} dash-functional @key{RET} Install an optional library of additional function combinators. @end table Alternatively, you can just dump @file{dash.el} or @file{dash-functional.el} in your load path somewhere. @menu * Using in a package:: Listing Dash as a package dependency. * Fontification of special variables:: Font Lock of anaphoric macro variables. @end menu @node Using in a package @section 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 (@pxref{Library Headers,,, elisp, The Emacs Lisp Reference Manual}). @lisp ;; Package-Requires: ((dash "@value{DASHVER}")) @end lisp The same goes for the @file{dash-functional.el} library of function combinators: @lisp ;; Package-Requires: ((dash "@value{DASHVER}") (dash-functional "@value{DASHFNVER}")) @end lisp @node Fontification of special variables @section Fontification of special variables @findex dash-fontify-mode The autoloaded minor mode @code{dash-fontify-mode} is provided for optional fontification of anaphoric Dash variables (@code{it}, @code{acc}, etc.@:) in Emacs Lisp buffers using search-based Font Lock (@pxref{Font Lock,,, emacs, The GNU Emacs Manual}). In older Emacs versions which do not dynamically detect macros, the minor mode also fontifies calls to Dash macros. @findex global-dash-fontify-mode To automatically enable the minor mode in all Emacs Lisp buffers, just call its autoloaded global counterpart @code{global-dash-fontify-mode}, either interactively or from your @code{user-init-file}: @lisp (global-dash-fontify-mode) @end lisp @node Functions @chapter Functions This chapter contains reference documentation for the Dash @acronym{API, Application Programming Interface}. The names of all public functions defined in the library are prefixed with a dash character (@samp{-}). The library also provides anaphoric macro versions of functions where that makes sense. The names of these macros are prefixed with two dashes (@samp{--}) instead of one. For instance, while the function @code{-map} applies a function to each element of a list, its anaphoric counterpart @code{--map} evaluates a form with the local variable @code{it} temporarily bound to the current list element instead. @lisp @group ;; Normal version. (-map (lambda (n) (* n n)) '(1 2 3 4)) @result{} (1 4 9 16) @end group @group ;; Anaphoric version. (--map (* it it) '(1 2 3 4)) @result{} (1 4 9 16) @end group @end lisp The normal version can, of course, also be written as in the following example, which demonstrates the utility of both versions. @lisp @group (defun my-square (n) "Return N multiplied by itself." (* n n)) (-map #'my-square '(1 2 3 4)) @result{} (1 4 9 16) @end group @end lisp @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:: @end menu @node Maps @section 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 new list. @anchor{-map} @defun -map (fn list) Return a new list consisting of the result of applying @var{fn} to the items in @var{list}. @example @group (-map (lambda (num) (* num num)) '(1 2 3 4)) @result{} '(1 4 9 16) @end group @group (-map 'square '(1 2 3 4)) @result{} '(1 4 9 16) @end group @group (--map (* it it) '(1 2 3 4)) @result{} '(1 4 9 16) @end group @end example @end defun @anchor{-map-when} @defun -map-when (pred rep list) Return a new list where the elements in @var{list} that do not match the @var{pred} function are unchanged, and where the elements in @var{list} that do match the @var{pred} function are mapped through the @var{rep} function. Alias: @code{-replace-where} See also: @code{-update-at} (@pxref{-update-at}) @example @group (-map-when 'even? 'square '(1 2 3 4)) @result{} '(1 4 3 16) @end group @group (--map-when (> it 2) (* it it) '(1 2 3 4)) @result{} '(1 2 9 16) @end group @group (--map-when (= it 2) 17 '(1 2 3 4)) @result{} '(1 17 3 4) @end group @end example @end defun @anchor{-map-first} @defun -map-first (pred rep list) Replace first item in @var{list} satisfying @var{pred} with result of @var{rep} called on this item. See also: @code{-map-when} (@pxref{-map-when}), @code{-replace-first} (@pxref{-replace-first}) @example @group (-map-first 'even? 'square '(1 2 3 4)) @result{} '(1 4 3 4) @end group @group (--map-first (> it 2) (* it it) '(1 2 3 4)) @result{} '(1 2 9 4) @end group @group (--map-first (= it 2) 17 '(1 2 3 2)) @result{} '(1 17 3 2) @end group @end example @end defun @anchor{-map-last} @defun -map-last (pred rep list) Replace last item in @var{list} satisfying @var{pred} with result of @var{rep} called on this item. See also: @code{-map-when} (@pxref{-map-when}), @code{-replace-last} (@pxref{-replace-last}) @example @group (-map-last 'even? 'square '(1 2 3 4)) @result{} '(1 2 3 16) @end group @group (--map-last (> it 2) (* it it) '(1 2 3 4)) @result{} '(1 2 3 16) @end group @group (--map-last (= it 2) 17 '(1 2 3 2)) @result{} '(1 2 3 17) @end group @end example @end defun @anchor{-map-indexed} @defun -map-indexed (fn list) Return a new list consisting of the result of (@var{fn} index item) for each item in @var{list}. In the anaphoric form @code{--map-indexed}, the index is exposed as symbol @code{it-index}. See also: @code{-each-indexed} (@pxref{-each-indexed}). @example @group (-map-indexed (lambda (index item) (- item index)) '(1 2 3 4)) @result{} '(1 1 1 1) @end group @group (--map-indexed (- it it-index) '(1 2 3 4)) @result{} '(1 1 1 1) @end group @end example @end defun @anchor{-annotate} @defun -annotate (fn list) Return a list of cons cells where each cell is @var{fn} applied to each element of @var{list} paired with the unmodified element of @var{list}. @example @group (-annotate '1+ '(1 2 3)) @result{} '((2 . 1) (3 . 2) (4 . 3)) @end group @group (-annotate 'length '(("h" "e" "l" "l" "o") ("hello" "world"))) @result{} '((5 "h" "e" "l" "l" "o") (2 "hello" "world")) @end group @group (--annotate (< 1 it) '(0 1 2 3)) @result{} '((nil . 0) (nil . 1) (t . 2) (t . 3)) @end group @end example @end defun @anchor{-splice} @defun -splice (pred fun list) Splice lists generated by @var{fun} in place of elements matching @var{pred} in @var{list}. @var{fun} takes the element matching @var{pred} as input. This function can be used as replacement for @code{,@@} in case you need to splice several lists at marked positions (for example with keywords). See also: @code{-splice-list} (@pxref{-splice-list}), @code{-insert-at} (@pxref{-insert-at}) @example @group (-splice 'even? (lambda (x) (list x x)) '(1 2 3 4)) @result{} '(1 2 2 3 4 4) @end group @group (--splice 't (list it it) '(1 2 3 4)) @result{} '(1 1 2 2 3 3 4 4) @end group @group (--splice (equal it :magic) '((list of) (magical) (code)) '((foo) (bar) :magic (baz))) @result{} '((foo) (bar) (list of) (magical) (code) (baz)) @end group @end example @end defun @anchor{-splice-list} @defun -splice-list (pred new-list list) Splice @var{new-list} in place of elements matching @var{pred} in @var{list}. See also: @code{-splice} (@pxref{-splice}), @code{-insert-at} (@pxref{-insert-at}) @example @group (-splice-list 'keywordp '(a b c) '(1 :foo 2)) @result{} '(1 a b c 2) @end group @group (-splice-list 'keywordp nil '(1 :foo 2)) @result{} '(1 2) @end group @group (--splice-list (keywordp it) '(a b c) '(1 :foo 2)) @result{} '(1 a b c 2) @end group @end example @end defun @anchor{-mapcat} @defun -mapcat (fn list) Return the concatenation of the result of mapping @var{fn} over @var{list}. Thus function @var{fn} should return a list. @example @group (-mapcat 'list '(1 2 3)) @result{} '(1 2 3) @end group @group (-mapcat (lambda (item) (list 0 item)) '(1 2 3)) @result{} '(0 1 0 2 0 3) @end group @group (--mapcat (list 0 it) '(1 2 3)) @result{} '(0 1 0 2 0 3) @end group @end example @end defun @anchor{-copy} @defun -copy (arg) Create a shallow copy of @var{list}. (fn @var{list}) @example @group (-copy '(1 2 3)) @result{} '(1 2 3) @end group @group (let ((a '(1 2 3))) (eq a (-copy a))) @result{} nil @end group @end example @end defun @node Sublist selection @section Sublist selection Functions returning a sublist of the original list. @anchor{-filter} @defun -filter (pred list) Return a new list of the items in @var{list} for which @var{pred} returns a non-nil value. Alias: @code{-select} See also: @code{-keep} (@pxref{-keep}), @code{-remove} (@pxref{-remove}). @example @group (-filter (lambda (num) (= 0 (% num 2))) '(1 2 3 4)) @result{} '(2 4) @end group @group (-filter 'even? '(1 2 3 4)) @result{} '(2 4) @end group @group (--filter (= 0 (% it 2)) '(1 2 3 4)) @result{} '(2 4) @end group @end example @end defun @anchor{-remove} @defun -remove (pred list) Return a new list of the items in @var{list} for which @var{pred} returns nil. Alias: @code{-reject} See also: @code{-filter} (@pxref{-filter}). @example @group (-remove (lambda (num) (= 0 (% num 2))) '(1 2 3 4)) @result{} '(1 3) @end group @group (-remove 'even? '(1 2 3 4)) @result{} '(1 3) @end group @group (--remove (= 0 (% it 2)) '(1 2 3 4)) @result{} '(1 3) @end group @end example @end defun @anchor{-remove-first} @defun -remove-first (pred list) Return a new list with the first item matching @var{pred} removed. Alias: @code{-reject-first} See also: @code{-remove} (@pxref{-remove}), @code{-map-first} (@pxref{-map-first}) @example @group (-remove-first 'even? '(1 3 5 4 7 8 10)) @result{} '(1 3 5 7 8 10) @end group @group (-remove-first 'stringp '(1 2 "first" "second" "third")) @result{} '(1 2 "second" "third") @end group @group (--remove-first (> it 3) '(1 2 3 4 5 6 7 8 9 10)) @result{} '(1 2 3 5 6 7 8 9 10) @end group @end example @end defun @anchor{-remove-last} @defun -remove-last (pred list) Return a new list with the last item matching @var{pred} removed. Alias: @code{-reject-last} See also: @code{-remove} (@pxref{-remove}), @code{-map-last} (@pxref{-map-last}) @example @group (-remove-last 'even? '(1 3 5 4 7 8 10 11)) @result{} '(1 3 5 4 7 8 11) @end group @group (-remove-last 'stringp '(1 2 "last" "second" "third")) @result{} '(1 2 "last" "second") @end group @group (--remove-last (> it 3) '(1 2 3 4 5 6 7 8 9 10)) @result{} '(1 2 3 4 5 6 7 8 9) @end group @end example @end defun @anchor{-remove-item} @defun -remove-item (item list) Remove all occurrences of @var{item} from @var{list}. Comparison is done with @code{equal}. @example @group (-remove-item 3 '(1 2 3 2 3 4 5 3)) @result{} '(1 2 2 4 5) @end group @group (-remove-item 'foo '(foo bar baz foo)) @result{} '(bar baz) @end group @group (-remove-item "bob" '("alice" "bob" "eve" "bob" "dave")) @result{} '("alice" "eve" "dave") @end group @end example @end defun @anchor{-non-nil} @defun -non-nil (list) Return all non-nil elements of @var{list}. @example @group (-non-nil '(1 nil 2 nil nil 3 4 nil 5 nil)) @result{} '(1 2 3 4 5) @end group @end example @end defun @anchor{-slice} @defun -slice (list from &optional to step) Return copy of @var{list}, starting from index @var{from} to index @var{to}. @var{from} or @var{to} may be negative. These values are then interpreted modulo the length of the list. If @var{step} is a number, only each STEPth item in the resulting section is returned. Defaults to 1. @example @group (-slice '(1 2 3 4 5) 1) @result{} '(2 3 4 5) @end group @group (-slice '(1 2 3 4 5) 0 3) @result{} '(1 2 3) @end group @group (-slice '(1 2 3 4 5 6 7 8 9) 1 -1 2) @result{} '(2 4 6 8) @end group @end example @end defun @anchor{-take} @defun -take (n list) Return a copy of the first @var{n} items in @var{list}. Return a copy of @var{list} if it contains @var{n} items or fewer. Return nil if @var{n} is zero or less. See also: @code{-take-last} (@pxref{-take-last}) @example @group (-take 3 '(1 2 3 4 5)) @result{} '(1 2 3) @end group @group (-take 17 '(1 2 3 4 5)) @result{} '(1 2 3 4 5) @end group @group (-take 0 '(1 2 3 4 5)) @result{} nil @end group @end example @end defun @anchor{-take-last} @defun -take-last (n list) Return a copy of the last @var{n} items of @var{list} in order. Return a copy of @var{list} if it contains @var{n} items or fewer. Return nil if @var{n} is zero or less. See also: @code{-take} (@pxref{-take}) @example @group (-take-last 3 '(1 2 3 4 5)) @result{} '(3 4 5) @end group @group (-take-last 17 '(1 2 3 4 5)) @result{} '(1 2 3 4 5) @end group @group (-take-last 1 '(1 2 3 4 5)) @result{} '(5) @end group @end example @end defun @anchor{-drop} @defun -drop (n list) Return a copy of the tail of @var{list} without the first @var{n} items. Return a copy of @var{list} if @var{n} is zero or less. Return nil if @var{list} contains @var{n} items or fewer. See also: @code{-drop-last} (@pxref{-drop-last}) @example @group (-drop 3 '(1 2 3 4 5)) @result{} '(4 5) @end group @group (-drop 17 '(1 2 3 4 5)) @result{} nil @end group @group (-drop 0 '(1 2 3 4 5)) @result{} '(1 2 3 4 5) @end group @end example @end defun @anchor{-drop-last} @defun -drop-last (n list) Return a copy of @var{list} without its last @var{n} items. Return a copy of @var{list} if @var{n} is zero or less. Return nil if @var{list} contains @var{n} items or fewer. See also: @code{-drop} (@pxref{-drop}) @example @group (-drop-last 3 '(1 2 3 4 5)) @result{} '(1 2) @end group @group (-drop-last 17 '(1 2 3 4 5)) @result{} nil @end group @group (-drop-last 0 '(1 2 3 4 5)) @result{} '(1 2 3 4 5) @end group @end example @end defun @anchor{-take-while} @defun -take-while (pred list) Take successive items from @var{list} for which @var{pred} returns non-nil. @var{pred} is a function of one argument. Return a new list of the successive elements from the start of @var{list} for which @var{pred} returns non-nil. See also: @code{-drop-while} (@pxref{-drop-while}) @example @group (-take-while 'even? '(1 2 3 4)) @result{} nil @end group @group (-take-while 'even? '(2 4 5 6)) @result{} '(2 4) @end group @group (--take-while (< it 4) '(1 2 3 4 3 2 1)) @result{} '(1 2 3) @end group @end example @end defun @anchor{-drop-while} @defun -drop-while (pred list) Drop successive items from @var{list} for which @var{pred} returns non-nil. @var{pred} is a function of one argument. Return a copy of the tail of @var{list} starting from its first element for which @var{pred} returns nil. See also: @code{-take-while} (@pxref{-take-while}) @example @group (-drop-while 'even? '(1 2 3 4)) @result{} '(1 2 3 4) @end group @group (-drop-while 'even? '(2 4 5 6)) @result{} '(5 6) @end group @group (--drop-while (< it 4) '(1 2 3 4 3 2 1)) @result{} '(4 3 2 1) @end group @end example @end defun @anchor{-select-by-indices} @defun -select-by-indices (indices list) Return a list whose elements are elements from @var{list} selected as `(nth i list)` for all i from @var{indices}. @example @group (-select-by-indices '(4 10 2 3 6) '("v" "e" "l" "o" "c" "i" "r" "a" "p" "t" "o" "r")) @result{} '("c" "o" "l" "o" "r") @end group @group (-select-by-indices '(2 1 0) '("a" "b" "c")) @result{} '("c" "b" "a") @end group @group (-select-by-indices '(0 1 2 0 1 3 3 1) '("f" "a" "r" "l")) @result{} '("f" "a" "r" "f" "a" "l" "l" "a") @end group @end example @end defun @anchor{-select-columns} @defun -select-columns (columns table) Select @var{columns} from @var{table}. @var{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 @var{columns} are selected. See also: @code{-select-column} (@pxref{-select-column}), @code{-select-by-indices} (@pxref{-select-by-indices}) @example @group (-select-columns '(0 2) '((1 2 3) (a b c) (:a :b :c))) @result{} '((1 3) (a c) (:a :c)) @end group @group (-select-columns '(1) '((1 2 3) (a b c) (:a :b :c))) @result{} '((2) (b) (:b)) @end group @group (-select-columns nil '((1 2 3) (a b c) (:a :b :c))) @result{} '(nil nil nil) @end group @end example @end defun @anchor{-select-column} @defun -select-column (column table) Select @var{column} from @var{table}. @var{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: @code{-select-columns} (@pxref{-select-columns}), @code{-select-by-indices} (@pxref{-select-by-indices}) @example @group (-select-column 1 '((1 2 3) (a b c) (:a :b :c))) @result{} '(2 b :b) @end group @end example @end defun @node List to list @section List to list Functions returning a modified copy of the input list. @anchor{-keep} @defun -keep (fn list) Return a new list of the non-nil results of applying @var{fn} to the items in @var{list}. If you want to select the original items satisfying a predicate use @code{-filter} (@pxref{-filter}). @example @group (-keep 'cdr '((1 2 3) (4 5) (6))) @result{} '((2 3) (5)) @end group @group (-keep (lambda (num) (when (> num 3) (* 10 num))) '(1 2 3 4 5 6)) @result{} '(40 50 60) @end group @group (--keep (when (> it 3) (* 10 it)) '(1 2 3 4 5 6)) @result{} '(40 50 60) @end group @end example @end defun @anchor{-concat} @defun -concat (&rest lists) Return a new list with the concatenation of the elements in the supplied @var{lists}. @example @group (-concat '(1)) @result{} '(1) @end group @group (-concat '(1) '(2)) @result{} '(1 2) @end group @group (-concat '(1) '(2 3) '(4)) @result{} '(1 2 3 4) @end group @end example @end defun @anchor{-flatten} @defun -flatten (l) Take a nested list @var{l} and return its contents as a single, flat list. Note that because @code{nil} represents a list of zero elements (an empty list), any mention of nil in @var{l} will disappear after flattening. If you need to preserve nils, consider @code{-flatten-n} (@pxref{-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: @code{-flatten-n} (@pxref{-flatten-n}) @example @group (-flatten '((1))) @result{} '(1) @end group @group (-flatten '((1 (2 3) (((4 (5))))))) @result{} '(1 2 3 4 5) @end group @group (-flatten '(1 2 (3 . 4))) @result{} '(1 2 (3 . 4)) @end group @end example @end defun @anchor{-flatten-n} @defun -flatten-n (num list) Flatten @var{num} levels of a nested @var{list}. See also: @code{-flatten} (@pxref{-flatten}) @example @group (-flatten-n 1 '((1 2) ((3 4) ((5 6))))) @result{} '(1 2 (3 4) ((5 6))) @end group @group (-flatten-n 2 '((1 2) ((3 4) ((5 6))))) @result{} '(1 2 3 4 (5 6)) @end group @group (-flatten-n 3 '((1 2) ((3 4) ((5 6))))) @result{} '(1 2 3 4 5 6) @end group @end example @end defun @anchor{-replace} @defun -replace (old new list) Replace all @var{old} items in @var{list} with @var{new}. Elements are compared using @code{equal}. See also: @code{-replace-at} (@pxref{-replace-at}) @example @group (-replace 1 "1" '(1 2 3 4 3 2 1)) @result{} '("1" 2 3 4 3 2 "1") @end group @group (-replace "foo" "bar" '("a" "nice" "foo" "sentence" "about" "foo")) @result{} '("a" "nice" "bar" "sentence" "about" "bar") @end group @group (-replace 1 2 nil) @result{} nil @end group @end example @end defun @anchor{-replace-first} @defun -replace-first (old new list) Replace the first occurrence of @var{old} with @var{new} in @var{list}. Elements are compared using @code{equal}. See also: @code{-map-first} (@pxref{-map-first}) @example @group (-replace-first 1 "1" '(1 2 3 4 3 2 1)) @result{} '("1" 2 3 4 3 2 1) @end group @group (-replace-first "foo" "bar" '("a" "nice" "foo" "sentence" "about" "foo")) @result{} '("a" "nice" "bar" "sentence" "about" "foo") @end group @group (-replace-first 1 2 nil) @result{} nil @end group @end example @end defun @anchor{-replace-last} @defun -replace-last (old new list) Replace the last occurrence of @var{old} with @var{new} in @var{list}. Elements are compared using @code{equal}. See also: @code{-map-last} (@pxref{-map-last}) @example @group (-replace-last 1 "1" '(1 2 3 4 3 2 1)) @result{} '(1 2 3 4 3 2 "1") @end group @group (-replace-last "foo" "bar" '("a" "nice" "foo" "sentence" "about" "foo")) @result{} '("a" "nice" "foo" "sentence" "about" "bar") @end group @group (-replace-last 1 2 nil) @result{} nil @end group @end example @end defun @anchor{-insert-at} @defun -insert-at (n x list) Return a list with @var{x} inserted into @var{list} at position @var{n}. See also: @code{-splice} (@pxref{-splice}), @code{-splice-list} (@pxref{-splice-list}) @example @group (-insert-at 1 'x '(a b c)) @result{} '(a x b c) @end group @group (-insert-at 12 'x '(a b c)) @result{} '(a b c x) @end group @end example @end defun @anchor{-replace-at} @defun -replace-at (n x list) Return a list with element at Nth position in @var{list} replaced with @var{x}. See also: @code{-replace} (@pxref{-replace}) @example @group (-replace-at 0 9 '(0 1 2 3 4 5)) @result{} '(9 1 2 3 4 5) @end group @group (-replace-at 1 9 '(0 1 2 3 4 5)) @result{} '(0 9 2 3 4 5) @end group @group (-replace-at 4 9 '(0 1 2 3 4 5)) @result{} '(0 1 2 3 9 5) @end group @end example @end defun @anchor{-update-at} @defun -update-at (n func list) Return a list with element at Nth position in @var{list} replaced with `(func (nth n list))`. See also: @code{-map-when} (@pxref{-map-when}) @example @group (-update-at 0 (lambda (x) (+ x 9)) '(0 1 2 3 4 5)) @result{} '(9 1 2 3 4 5) @end group @group (-update-at 1 (lambda (x) (+ x 8)) '(0 1 2 3 4 5)) @result{} '(0 9 2 3 4 5) @end group @group (--update-at 2 (length it) '("foo" "bar" "baz" "quux")) @result{} '("foo" "bar" 3 "quux") @end group @end example @end defun @anchor{-remove-at} @defun -remove-at (n list) Return a list with element at Nth position in @var{list} removed. See also: @code{-remove-at-indices} (@pxref{-remove-at-indices}), @code{-remove} (@pxref{-remove}) @example @group (-remove-at 0 '("0" "1" "2" "3" "4" "5")) @result{} '("1" "2" "3" "4" "5") @end group @group (-remove-at 1 '("0" "1" "2" "3" "4" "5")) @result{} '("0" "2" "3" "4" "5") @end group @group (-remove-at 2 '("0" "1" "2" "3" "4" "5")) @result{} '("0" "1" "3" "4" "5") @end group @end example @end defun @anchor{-remove-at-indices} @defun -remove-at-indices (indices list) Return a list whose elements are elements from @var{list} without elements selected as `(nth i list)` for all i from @var{indices}. See also: @code{-remove-at} (@pxref{-remove-at}), @code{-remove} (@pxref{-remove}) @example @group (-remove-at-indices '(0) '("0" "1" "2" "3" "4" "5")) @result{} '("1" "2" "3" "4" "5") @end group @group (-remove-at-indices '(0 2 4) '("0" "1" "2" "3" "4" "5")) @result{} '("1" "3" "5") @end group @group (-remove-at-indices '(0 5) '("0" "1" "2" "3" "4" "5")) @result{} '("1" "2" "3" "4") @end group @end example @end defun @node Reductions @section Reductions Functions reducing lists into single value. @anchor{-reduce-from} @defun -reduce-from (fn initial-value list) Return the result of applying @var{fn} to @var{initial-value} and the first item in @var{list}, then applying @var{fn} to that result and the 2nd item, etc. If @var{list} contains no items, return @var{initial-value} and do not call @var{fn}. In the anaphoric form @code{--reduce-from}, the accumulated value is exposed as symbol @code{acc}. See also: @code{-reduce} (@pxref{-reduce}), @code{-reduce-r} (@pxref{-reduce-r}) @example @group (-reduce-from '- 10 '(1 2 3)) @result{} 4 @end group @group (-reduce-from (lambda (memo item) (format "(%s - %d)" memo item)) "10" '(1 2 3)) @result{} "(((10 - 1) - 2) - 3)" @end group @group (--reduce-from (concat acc " " it) "START" '("a" "b" "c")) @result{} "START a b c" @end group @end example @end defun @anchor{-reduce-r-from} @defun -reduce-r-from (fn initial-value list) Replace conses with @var{fn}, nil with @var{initial-value} and evaluate the resulting expression. If @var{list} is empty, @var{initial-value} is returned and @var{fn} is not called. Note: this function works the same as @code{-reduce-from} (@pxref{-reduce-from}) but the operation associates from right instead of from left. See also: @code{-reduce-r} (@pxref{-reduce-r}), @code{-reduce} (@pxref{-reduce}) @example @group (-reduce-r-from '- 10 '(1 2 3)) @result{} -8 @end group @group (-reduce-r-from (lambda (item memo) (format "(%d - %s)" item memo)) "10" '(1 2 3)) @result{} "(1 - (2 - (3 - 10)))" @end group @group (--reduce-r-from (concat it " " acc) "END" '("a" "b" "c")) @result{} "a b c END" @end group @end example @end defun @anchor{-reduce} @defun -reduce (fn list) Return the result of applying @var{fn} to the first 2 items in @var{list}, then applying @var{fn} to that result and the 3rd item, etc. If @var{list} contains no items, return the result of calling @var{fn} with no arguments. If @var{list} contains a single item, return that item and do not call @var{fn}. In the anaphoric form @code{--reduce}, the accumulated value is exposed as symbol @code{acc}. See also: @code{-reduce-from} (@pxref{-reduce-from}), @code{-reduce-r} (@pxref{-reduce-r}) @example @group (-reduce '- '(1 2 3 4)) @result{} -8 @end group @group (-reduce 'list '(1 2 3 4)) @result{} '(((1 2) 3) 4) @end group @group (--reduce (format "%s-%d" acc it) '(1 2 3)) @result{} "1-2-3" @end group @end example @end defun @anchor{-reduce-r} @defun -reduce-r (fn list) Replace conses with @var{fn} and evaluate the resulting expression. The final nil is ignored. If @var{list} contains no items, return the result of calling @var{fn} with no arguments. If @var{list} contains a single item, return that item and do not call @var{fn}. The first argument of @var{fn} is the new item, the second is the accumulated value. Note: this function works the same as @code{-reduce} (@pxref{-reduce}) but the operation associates from right instead of from left. See also: @code{-reduce-r-from} (@pxref{-reduce-r-from}), @code{-reduce} (@pxref{-reduce}) @example @group (-reduce-r '- '(1 2 3 4)) @result{} -2 @end group @group (-reduce-r (lambda (item memo) (format "%s-%d" memo item)) '(1 2 3)) @result{} "3-2-1" @end group @group (--reduce-r (format "%s-%d" acc it) '(1 2 3)) @result{} "3-2-1" @end group @end example @end defun @anchor{-reductions-from} @defun -reductions-from (fn init list) Return a list of the intermediate values of the reduction. See @code{-reduce-from} (@pxref{-reduce-from}) for explanation of the arguments. See also: @code{-reductions} (@pxref{-reductions}), @code{-reductions-r} (@pxref{-reductions-r}), @code{-reduce-r} (@pxref{-reduce-r}) @example @group (-reductions-from (lambda (a i) (format "(%s FN %d)" a i)) "INIT" '(1 2 3 4)) @result{} '("INIT" "(INIT FN 1)" "((INIT FN 1) FN 2)" "(((INIT FN 1) FN 2) FN 3)" "((((INIT FN 1) FN 2) FN 3) FN 4)") @end group @group (-reductions-from 'max 0 '(2 1 4 3)) @result{} '(0 2 2 4 4) @end group @group (-reductions-from '* 1 '(1 2 3 4)) @result{} '(1 1 2 6 24) @end group @end example @end defun @anchor{-reductions-r-from} @defun -reductions-r-from (fn init list) Return a list of the intermediate values of the reduction. See @code{-reduce-r-from} (@pxref{-reduce-r-from}) for explanation of the arguments. See also: @code{-reductions-r} (@pxref{-reductions-r}), @code{-reductions} (@pxref{-reductions}), @code{-reduce} (@pxref{-reduce}) @example @group (-reductions-r-from (lambda (i a) (format "(%d FN %s)" i a)) "INIT" '(1 2 3 4)) @result{} '("(1 FN (2 FN (3 FN (4 FN INIT))))" "(2 FN (3 FN (4 FN INIT)))" "(3 FN (4 FN INIT))" "(4 FN INIT)" "INIT") @end group @group (-reductions-r-from 'max 0 '(2 1 4 3)) @result{} '(4 4 4 3 0) @end group @group (-reductions-r-from '* 1 '(1 2 3 4)) @result{} '(24 24 12 4 1) @end group @end example @end defun @anchor{-reductions} @defun -reductions (fn list) Return a list of the intermediate values of the reduction. See @code{-reduce} (@pxref{-reduce}) for explanation of the arguments. See also: @code{-reductions-from} (@pxref{-reductions-from}), @code{-reductions-r} (@pxref{-reductions-r}), @code{-reduce-r} (@pxref{-reduce-r}) @example @group (-reductions (lambda (a i) (format "(%s FN %d)" a i)) '(1 2 3 4)) @result{} '(1 "(1 FN 2)" "((1 FN 2) FN 3)" "(((1 FN 2) FN 3) FN 4)") @end group @group (-reductions '+ '(1 2 3 4)) @result{} '(1 3 6 10) @end group @group (-reductions '* '(1 2 3 4)) @result{} '(1 2 6 24) @end group @end example @end defun @anchor{-reductions-r} @defun -reductions-r (fn list) Return a list of the intermediate values of the reduction. See @code{-reduce-r} (@pxref{-reduce-r}) for explanation of the arguments. See also: @code{-reductions-r-from} (@pxref{-reductions-r-from}), @code{-reductions} (@pxref{-reductions}), @code{-reduce} (@pxref{-reduce}) @example @group (-reductions-r (lambda (i a) (format "(%d FN %s)" i a)) '(1 2 3 4)) @result{} '("(1 FN (2 FN (3 FN 4)))" "(2 FN (3 FN 4))" "(3 FN 4)" 4) @end group @group (-reductions-r '+ '(1 2 3 4)) @result{} '(10 9 7 4) @end group @group (-reductions-r '* '(1 2 3 4)) @result{} '(24 24 12 4) @end group @end example @end defun @anchor{-count} @defun -count (pred list) Counts the number of items in @var{list} where (@var{pred} item) is non-nil. @example @group (-count 'even? '(1 2 3 4 5)) @result{} 2 @end group @group (--count (< it 4) '(1 2 3 4)) @result{} 3 @end group @end example @end defun @anchor{-sum} @defun -sum (list) Return the sum of @var{list}. @example @group (-sum '()) @result{} 0 @end group @group (-sum '(1)) @result{} 1 @end group @group (-sum '(1 2 3 4)) @result{} 10 @end group @end example @end defun @anchor{-running-sum} @defun -running-sum (list) Return a list with running sums of items in @var{list}. @var{list} must be non-empty. @example @group (-running-sum '(1 2 3 4)) @result{} '(1 3 6 10) @end group @group (-running-sum '(1)) @result{} '(1) @end group @group (-running-sum '()) @result{} error @end group @end example @end defun @anchor{-product} @defun -product (list) Return the product of @var{list}. @example @group (-product '()) @result{} 1 @end group @group (-product '(1)) @result{} 1 @end group @group (-product '(1 2 3 4)) @result{} 24 @end group @end example @end defun @anchor{-running-product} @defun -running-product (list) Return a list with running products of items in @var{list}. @var{list} must be non-empty. @example @group (-running-product '(1 2 3 4)) @result{} '(1 2 6 24) @end group @group (-running-product '(1)) @result{} '(1) @end group @group (-running-product '()) @result{} error @end group @end example @end defun @anchor{-inits} @defun -inits (list) Return all prefixes of @var{list}. @example @group (-inits '(1 2 3 4)) @result{} '(nil (1) (1 2) (1 2 3) (1 2 3 4)) @end group @group (-inits nil) @result{} '(nil) @end group @group (-inits '(1)) @result{} '(nil (1)) @end group @end example @end defun @anchor{-tails} @defun -tails (list) Return all suffixes of @var{list} @example @group (-tails '(1 2 3 4)) @result{} '((1 2 3 4) (2 3 4) (3 4) (4) nil) @end group @group (-tails nil) @result{} '(nil) @end group @group (-tails '(1)) @result{} '((1) nil) @end group @end example @end defun @anchor{-common-prefix} @defun -common-prefix (&rest lists) Return the longest common prefix of @var{lists}. @example @group (-common-prefix '(1)) @result{} '(1) @end group @group (-common-prefix '(1 2) '(3 4) '(1 2)) @result{} nil @end group @group (-common-prefix '(1 2) '(1 2 3) '(1 2 3 4)) @result{} '(1 2) @end group @end example @end defun @anchor{-common-suffix} @defun -common-suffix (&rest lists) Return the longest common suffix of @var{lists}. @example @group (-common-suffix '(1)) @result{} '(1) @end group @group (-common-suffix '(1 2) '(3 4) '(1 2)) @result{} nil @end group @group (-common-suffix '(1 2 3 4) '(2 3 4) '(3 4)) @result{} '(3 4) @end group @end example @end defun @anchor{-min} @defun -min (list) Return the smallest value from @var{list} of numbers or markers. @example @group (-min '(0)) @result{} 0 @end group @group (-min '(3 2 1)) @result{} 1 @end group @group (-min '(1 2 3)) @result{} 1 @end group @end example @end defun @anchor{-min-by} @defun -min-by (comparator list) Take a comparison function @var{comparator} and a @var{list} and return the least element of the list by the comparison function. See also combinator @code{-on} (@pxref{-on}) which can transform the values before comparing them. @example @group (-min-by '> '(4 3 6 1)) @result{} 1 @end group @group (--min-by (> (car it) (car other)) '((1 2 3) (2) (3 2))) @result{} '(1 2 3) @end group @group (--min-by (> (length it) (length other)) '((1 2 3) (2) (3 2))) @result{} '(2) @end group @end example @end defun @anchor{-max} @defun -max (list) Return the largest value from @var{list} of numbers or markers. @example @group (-max '(0)) @result{} 0 @end group @group (-max '(3 2 1)) @result{} 3 @end group @group (-max '(1 2 3)) @result{} 3 @end group @end example @end defun @anchor{-max-by} @defun -max-by (comparator list) Take a comparison function @var{comparator} and a @var{list} and return the greatest element of the list by the comparison function. See also combinator @code{-on} (@pxref{-on}) which can transform the values before comparing them. @example @group (-max-by '> '(4 3 6 1)) @result{} 6 @end group @group (--max-by (> (car it) (car other)) '((1 2 3) (2) (3 2))) @result{} '(3 2) @end group @group (--max-by (> (length it) (length other)) '((1 2 3) (2) (3 2))) @result{} '(1 2 3) @end group @end example @end defun @node Unfolding @section Unfolding Operations dual to reductions, building lists from a seed value rather than consuming a list to produce a single value. @anchor{-iterate} @defun -iterate (fun init n) Return a list of iterated applications of @var{fun} to @var{init}. This means a list of the form: (@var{init} (@var{fun} @var{init}) (@var{fun} (@var{fun} @var{init})) @dots{}) @var{n} is the length of the returned list. @example @group (-iterate #'1+ 1 10) @result{} '(1 2 3 4 5 6 7 8 9 10) @end group @group (-iterate (lambda (x) (+ x x)) 2 5) @result{} '(2 4 8 16 32) @end group @group (--iterate (* it it) 2 5) @result{} '(2 4 16 256 65536) @end group @end example @end defun @anchor{-unfold} @defun -unfold (fun seed) Build a list from @var{seed} using @var{fun}. This is "dual" operation to @code{-reduce-r} (@pxref{-reduce-r}): while -reduce-r consumes a list to produce a single value, @code{-unfold} (@pxref{-unfold}) takes a seed value and builds a (potentially infinite!) list. @var{fun} should return @code{nil} to stop the generating process, or a cons (@var{a} . @var{b}), where @var{a} will be prepended to the result and @var{b} is the new seed. @example @group (-unfold (lambda (x) (unless (= x 0) (cons x (1- x)))) 10) @result{} '(10 9 8 7 6 5 4 3 2 1) @end group @group (--unfold (when it (cons it (cdr it))) '(1 2 3 4)) @result{} '((1 2 3 4) (2 3 4) (3 4) (4)) @end group @group (--unfold (when it (cons it (butlast it))) '(1 2 3 4)) @result{} '((1 2 3 4) (1 2 3) (1 2) (1)) @end group @end example @end defun @node Predicates @section Predicates @anchor{-any?} @defun -any? (pred list) Return t if (@var{pred} x) is non-nil for any x in @var{list}, else nil. Alias: @code{-any-p}, @code{-some?}, @code{-some-p} @example @group (-any? 'even? '(1 2 3)) @result{} t @end group @group (-any? 'even? '(1 3 5)) @result{} nil @end group @group (-any? 'null '(1 3 5)) @result{} nil @end group @end example @end defun @anchor{-all?} @defun -all? (pred list) Return t if (@var{pred} x) is non-nil for all x in @var{list}, else nil. Alias: @code{-all-p}, @code{-every?}, @code{-every-p} @example @group (-all? 'even? '(1 2 3)) @result{} nil @end group @group (-all? 'even? '(2 4 6)) @result{} t @end group @group (--all? (= 0 (% it 2)) '(2 4 6)) @result{} t @end group @end example @end defun @anchor{-none?} @defun -none? (pred list) Return t if (@var{pred} x) is nil for all x in @var{list}, else nil. Alias: @code{-none-p} @example @group (-none? 'even? '(1 2 3)) @result{} nil @end group @group (-none? 'even? '(1 3 5)) @result{} t @end group @group (--none? (= 0 (% it 2)) '(1 2 3)) @result{} nil @end group @end example @end defun @anchor{-only-some?} @defun -only-some? (pred list) Return `t` if at least one item of @var{list} matches @var{pred} and at least one item of @var{list} does not match @var{pred}. Return `nil` both if all items match the predicate or if none of the items match the predicate. Alias: @code{-only-some-p} @example @group (-only-some? 'even? '(1 2 3)) @result{} t @end group @group (-only-some? 'even? '(1 3 5)) @result{} nil @end group @group (-only-some? 'even? '(2 4 6)) @result{} nil @end group @end example @end defun @anchor{-contains?} @defun -contains? (list element) Return non-nil if @var{list} contains @var{element}. The test for equality is done with @code{equal}, or with @code{-compare-fn} if that's non-nil. Alias: @code{-contains-p} @example @group (-contains? '(1 2 3) 1) @result{} t @end group @group (-contains? '(1 2 3) 2) @result{} t @end group @group (-contains? '(1 2 3) 4) @result{} nil @end group @end example @end defun @anchor{-same-items?} @defun -same-items? (list list2) Return true if @var{list} and @var{list2} has the same items. The order of the elements in the lists does not matter. Alias: @code{-same-items-p} @example @group (-same-items? '(1 2 3) '(1 2 3)) @result{} t @end group @group (-same-items? '(1 2 3) '(3 2 1)) @result{} t @end group @group (-same-items? '(1 2 3) '(1 2 3 4)) @result{} nil @end group @end example @end defun @anchor{-is-prefix?} @defun -is-prefix? (prefix list) Return non-nil if @var{prefix} is prefix of @var{list}. Alias: @code{-is-prefix-p} @example @group (-is-prefix? '(1 2 3) '(1 2 3 4 5)) @result{} t @end group @group (-is-prefix? '(1 2 3 4 5) '(1 2 3)) @result{} nil @end group @group (-is-prefix? '(1 3) '(1 2 3 4 5)) @result{} nil @end group @end example @end defun @anchor{-is-suffix?} @defun -is-suffix? (suffix list) Return non-nil if @var{suffix} is suffix of @var{list}. Alias: @code{-is-suffix-p} @example @group (-is-suffix? '(3 4 5) '(1 2 3 4 5)) @result{} t @end group @group (-is-suffix? '(1 2 3 4 5) '(3 4 5)) @result{} nil @end group @group (-is-suffix? '(3 5) '(1 2 3 4 5)) @result{} nil @end group @end example @end defun @anchor{-is-infix?} @defun -is-infix? (infix list) Return non-nil if @var{infix} is infix of @var{list}. This operation runs in @var{o}(n^2) time Alias: @code{-is-infix-p} @example @group (-is-infix? '(1 2 3) '(1 2 3 4 5)) @result{} t @end group @group (-is-infix? '(2 3 4) '(1 2 3 4 5)) @result{} t @end group @group (-is-infix? '(3 4 5) '(1 2 3 4 5)) @result{} t @end group @end example @end defun @node Partitioning @section Partitioning Functions partitioning the input list into a list of lists. @anchor{-split-at} @defun -split-at (n list) Return a list of ((-take @var{n} @var{list}) (-drop @var{n} @var{list})), in no more than one pass through the list. @example @group (-split-at 3 '(1 2 3 4 5)) @result{} '((1 2 3) (4 5)) @end group @group (-split-at 17 '(1 2 3 4 5)) @result{} '((1 2 3 4 5) nil) @end group @end example @end defun @anchor{-split-with} @defun -split-with (pred list) Return a list of ((-take-while @var{pred} @var{list}) (-drop-while @var{pred} @var{list})), in no more than one pass through the list. @example @group (-split-with 'even? '(1 2 3 4)) @result{} '(nil (1 2 3 4)) @end group @group (-split-with 'even? '(2 4 5 6)) @result{} '((2 4) (5 6)) @end group @group (--split-with (< it 4) '(1 2 3 4 3 2 1)) @result{} '((1 2 3) (4 3 2 1)) @end group @end example @end defun @anchor{-split-on} @defmac -split-on (item list) Split the @var{list} each time @var{item} is found. Unlike @code{-partition-by} (@pxref{-partition-by}), the @var{item} is discarded from the results. Empty lists are also removed from the result. Comparison is done by @code{equal}. See also @code{-split-when} (@pxref{-split-when}) @example @group (-split-on '| '(Nil | Leaf a | Node [Tree a])) @result{} '((Nil) (Leaf a) (Node [Tree a])) @end group @group (-split-on ':endgroup '("a" "b" :endgroup "c" :endgroup "d" "e")) @result{} '(("a" "b") ("c") ("d" "e")) @end group @group (-split-on ':endgroup '("a" "b" :endgroup :endgroup "d" "e")) @result{} '(("a" "b") ("d" "e")) @end group @end example @end defmac @anchor{-split-when} @defun -split-when (fn list) Split the @var{list} on each element where @var{fn} returns non-nil. Unlike @code{-partition-by} (@pxref{-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 @code{split-string}. @example @group (-split-when 'even? '(1 2 3 4 5 6)) @result{} '((1) (3) (5)) @end group @group (-split-when 'even? '(1 2 3 4 6 8 9)) @result{} '((1) (3) (9)) @end group @group (--split-when (memq it '(&optional &rest)) '(a b &optional c d &rest args)) @result{} '((a b) (c d) (args)) @end group @end example @end defun @anchor{-separate} @defun -separate (pred list) Return a list of ((-filter @var{pred} @var{list}) (-remove @var{pred} @var{list})), in one pass through the list. @example @group (-separate (lambda (num) (= 0 (% num 2))) '(1 2 3 4 5 6 7)) @result{} '((2 4 6) (1 3 5 7)) @end group @group (--separate (< it 5) '(3 7 5 9 3 2 1 4 6)) @result{} '((3 3 2 1 4) (7 5 9 6)) @end group @group (-separate 'cdr '((1 2) (1) (1 2 3) (4))) @result{} '(((1 2) (1 2 3)) ((1) (4))) @end group @end example @end defun @anchor{-partition} @defun -partition (n list) Return a new list with the items in @var{list} grouped into @var{n-}sized sublists. If there are not enough items to make the last group @var{n-}sized, those items are discarded. @example @group (-partition 2 '(1 2 3 4 5 6)) @result{} '((1 2) (3 4) (5 6)) @end group @group (-partition 2 '(1 2 3 4 5 6 7)) @result{} '((1 2) (3 4) (5 6)) @end group @group (-partition 3 '(1 2 3 4 5 6 7)) @result{} '((1 2 3) (4 5 6)) @end group @end example @end defun @anchor{-partition-all} @defun -partition-all (n list) Return a new list with the items in @var{list} grouped into @var{n-}sized sublists. The last group may contain less than @var{n} items. @example @group (-partition-all 2 '(1 2 3 4 5 6)) @result{} '((1 2) (3 4) (5 6)) @end group @group (-partition-all 2 '(1 2 3 4 5 6 7)) @result{} '((1 2) (3 4) (5 6) (7)) @end group @group (-partition-all 3 '(1 2 3 4 5 6 7)) @result{} '((1 2 3) (4 5 6) (7)) @end group @end example @end defun @anchor{-partition-in-steps} @defun -partition-in-steps (n step list) Return a new list with the items in @var{list} grouped into @var{n-}sized sublists at offsets @var{step} apart. If there are not enough items to make the last group @var{n-}sized, those items are discarded. @example @group (-partition-in-steps 2 1 '(1 2 3 4)) @result{} '((1 2) (2 3) (3 4)) @end group @group (-partition-in-steps 3 2 '(1 2 3 4)) @result{} '((1 2 3)) @end group @group (-partition-in-steps 3 2 '(1 2 3 4 5)) @result{} '((1 2 3) (3 4 5)) @end group @end example @end defun @anchor{-partition-all-in-steps} @defun -partition-all-in-steps (n step list) Return a new list with the items in @var{list} grouped into @var{n-}sized sublists at offsets @var{step} apart. The last groups may contain less than @var{n} items. @example @group (-partition-all-in-steps 2 1 '(1 2 3 4)) @result{} '((1 2) (2 3) (3 4) (4)) @end group @group (-partition-all-in-steps 3 2 '(1 2 3 4)) @result{} '((1 2 3) (3 4)) @end group @group (-partition-all-in-steps 3 2 '(1 2 3 4 5)) @result{} '((1 2 3) (3 4 5) (5)) @end group @end example @end defun @anchor{-partition-by} @defun -partition-by (fn list) Apply @var{fn} to each item in @var{list}, splitting it each time @var{fn} returns a new value. @example @group (-partition-by 'even? '()) @result{} '() @end group @group (-partition-by 'even? '(1 1 2 2 2 3 4 6 8)) @result{} '((1 1) (2 2 2) (3) (4 6 8)) @end group @group (--partition-by (< it 3) '(1 2 3 4 3 2 1)) @result{} '((1 2) (3 4 3) (2 1)) @end group @end example @end defun @anchor{-partition-by-header} @defun -partition-by-header (fn list) Apply @var{fn} to the first item in @var{list}. That is the header value. Apply @var{fn} to each item in @var{list}, splitting it each time @var{fn} returns the header value, but only after seeing at least one other value (the body). @example @group (--partition-by-header (= it 1) '(1 2 3 1 2 1 2 3 4)) @result{} '((1 2 3) (1 2) (1 2 3 4)) @end group @group (--partition-by-header (> it 0) '(1 2 0 1 0 1 2 3 0)) @result{} '((1 2 0) (1 0) (1 2 3 0)) @end group @group (-partition-by-header 'even? '(2 1 1 1 4 1 3 5 6 6 1)) @result{} '((2 1 1 1) (4 1 3 5) (6 6 1)) @end group @end example @end defun @anchor{-partition-after-pred} @defun -partition-after-pred (pred list) Partition directly after each time @var{pred} is true on an element of @var{list}. @example @group (-partition-after-pred #'odd? '()) @result{} '() @end group @group (-partition-after-pred #'odd? '(1)) @result{} '((1)) @end group @group (-partition-after-pred #'odd? '(0 1)) @result{} '((0 1)) @end group @end example @end defun @anchor{-partition-before-pred} @defun -partition-before-pred (pred list) Partition directly before each time @var{pred} is true on an element of @var{list}. @example @group (-partition-before-pred #'odd? '()) @result{} '() @end group @group (-partition-before-pred #'odd? '(1)) @result{} '((1)) @end group @group (-partition-before-pred #'odd? '(0 1)) @result{} '((0) (1)) @end group @end example @end defun @anchor{-partition-before-item} @defun -partition-before-item (item list) Partition directly before each time @var{item} appears in @var{list}. @example @group (-partition-before-item 3 '()) @result{} '() @end group @group (-partition-before-item 3 '(1)) @result{} '((1)) @end group @group (-partition-before-item 3 '(3)) @result{} '((3)) @end group @end example @end defun @anchor{-partition-after-item} @defun -partition-after-item (item list) Partition directly after each time @var{item} appears in @var{list}. @example @group (-partition-after-item 3 '()) @result{} '() @end group @group (-partition-after-item 3 '(1)) @result{} '((1)) @end group @group (-partition-after-item 3 '(3)) @result{} '((3)) @end group @end example @end defun @anchor{-group-by} @defun -group-by (fn list) Separate @var{list} into an alist whose keys are @var{fn} applied to the elements of @var{list}. Keys are compared by @code{equal}. @example @group (-group-by 'even? '()) @result{} '() @end group @group (-group-by 'even? '(1 1 2 2 2 3 4 6 8)) @result{} '((nil 1 1 3) (t 2 2 2 4 6 8)) @end group @group (--group-by (car (split-string it "/")) '("a/b" "c/d" "a/e")) @result{} '(("a" "a/b" "a/e") ("c" "c/d")) @end group @end example @end defun @node Indexing @section Indexing Return indices of elements based on predicates, sort elements by indices etc. @anchor{-elem-index} @defun -elem-index (elem list) Return the index of the first element in the given @var{list} which is equal to the query element @var{elem}, or nil if there is no such element. @example @group (-elem-index 2 '(6 7 8 2 3 4)) @result{} 3 @end group @group (-elem-index "bar" '("foo" "bar" "baz")) @result{} 1 @end group @group (-elem-index '(1 2) '((3) (5 6) (1 2) nil)) @result{} 2 @end group @end example @end defun @anchor{-elem-indices} @defun -elem-indices (elem list) Return the indices of all elements in @var{list} equal to the query element @var{elem}, in ascending order. @example @group (-elem-indices 2 '(6 7 8 2 3 4 2 1)) @result{} '(3 6) @end group @group (-elem-indices "bar" '("foo" "bar" "baz")) @result{} '(1) @end group @group (-elem-indices '(1 2) '((3) (1 2) (5 6) (1 2) nil)) @result{} '(1 3) @end group @end example @end defun @anchor{-find-index} @defun -find-index (pred list) Take a predicate @var{pred} and a @var{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 @code{-first} (@pxref{-first}). @example @group (-find-index 'even? '(2 4 1 6 3 3 5 8)) @result{} 0 @end group @group (--find-index (< 5 it) '(2 4 1 6 3 3 5 8)) @result{} 3 @end group @group (-find-index (-partial 'string-lessp "baz") '("bar" "foo" "baz")) @result{} 1 @end group @end example @end defun @anchor{-find-last-index} @defun -find-last-index (pred list) Take a predicate @var{pred} and a @var{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 @code{-last} (@pxref{-last}). @example @group (-find-last-index 'even? '(2 4 1 6 3 3 5 8)) @result{} 7 @end group @group (--find-last-index (< 5 it) '(2 7 1 6 3 8 5 2)) @result{} 5 @end group @group (-find-last-index (-partial 'string-lessp "baz") '("q" "foo" "baz")) @result{} 1 @end group @end example @end defun @anchor{-find-indices} @defun -find-indices (pred list) Return the indices of all elements in @var{list} satisfying the predicate @var{pred}, in ascending order. @example @group (-find-indices 'even? '(2 4 1 6 3 3 5 8)) @result{} '(0 1 3 7) @end group @group (--find-indices (< 5 it) '(2 4 1 6 3 3 5 8)) @result{} '(3 7) @end group @group (-find-indices (-partial 'string-lessp "baz") '("bar" "foo" "baz")) @result{} '(1) @end group @end example @end defun @anchor{-grade-up} @defun -grade-up (comparator list) Grade elements of @var{list} using @var{comparator} relation, yielding a permutation vector such that applying this permutation to @var{list} sorts it in ascending order. @example @group (-grade-up '< '(3 1 4 2 1 3 3)) @result{} '(1 4 3 0 5 6 2) @end group @group (let ((l '(3 1 4 2 1 3 3))) (-select-by-indices (-grade-up '< l) l)) @result{} '(1 1 2 3 3 3 4) @end group @end example @end defun @anchor{-grade-down} @defun -grade-down (comparator list) Grade elements of @var{list} using @var{comparator} relation, yielding a permutation vector such that applying this permutation to @var{list} sorts it in descending order. @example @group (-grade-down '< '(3 1 4 2 1 3 3)) @result{} '(2 0 5 6 3 1 4) @end group @group (let ((l '(3 1 4 2 1 3 3))) (-select-by-indices (-grade-down '< l) l)) @result{} '(4 3 3 3 2 1 1) @end group @end example @end defun @node Set operations @section Set operations Operations pretending lists are sets. @anchor{-union} @defun -union (list list2) Return a new list containing the elements of @var{list} and elements of @var{list2} that are not in @var{list}. The test for equality is done with @code{equal}, or with @code{-compare-fn} if that's non-nil. @example @group (-union '(1 2 3) '(3 4 5)) @result{} '(1 2 3 4 5) @end group @group (-union '(1 2 3 4) '()) @result{} '(1 2 3 4) @end group @group (-union '(1 1 2 2) '(3 2 1)) @result{} '(1 1 2 2 3) @end group @end example @end defun @anchor{-difference} @defun -difference (list list2) Return a new list with only the members of @var{list} that are not in @var{list2}. The test for equality is done with @code{equal}, or with @code{-compare-fn} if that's non-nil. @example @group (-difference '() '()) @result{} '() @end group @group (-difference '(1 2 3) '(4 5 6)) @result{} '(1 2 3) @end group @group (-difference '(1 2 3 4) '(3 4 5 6)) @result{} '(1 2) @end group @end example @end defun @anchor{-intersection} @defun -intersection (list list2) Return a new list containing only the elements that are members of both @var{list} and @var{list2}. The test for equality is done with @code{equal}, or with @code{-compare-fn} if that's non-nil. @example @group (-intersection '() '()) @result{} '() @end group @group (-intersection '(1 2 3) '(4 5 6)) @result{} '() @end group @group (-intersection '(1 2 3 4) '(3 4 5 6)) @result{} '(3 4) @end group @end example @end defun @anchor{-powerset} @defun -powerset (list) Return the power set of @var{list}. @example @group (-powerset '()) @result{} '(nil) @end group @group (-powerset '(x y z)) @result{} '((x y z) (x y) (x z) (x) (y z) (y) (z) nil) @end group @end example @end defun @anchor{-permutations} @defun -permutations (list) Return the permutations of @var{list}. @example @group (-permutations '()) @result{} '(nil) @end group @group (-permutations '(1 2)) @result{} '((1 2) (2 1)) @end group @group (-permutations '(a b c)) @result{} '((a b c) (a c b) (b a c) (b c a) (c a b) (c b a)) @end group @end example @end defun @anchor{-distinct} @defun -distinct (list) Return a new list with all duplicates removed. The test for equality is done with @code{equal}, or with @code{-compare-fn} if that's non-nil. Alias: @code{-uniq} @example @group (-distinct '()) @result{} '() @end group @group (-distinct '(1 2 2 4)) @result{} '(1 2 4) @end group @group (-distinct '(t t t)) @result{} '(t) @end group @end example @end defun @node Other list operations @section Other list operations Other list functions not fit to be classified elsewhere. @anchor{-rotate} @defun -rotate (n list) Rotate @var{list} @var{n} places to the right. With @var{n} negative, rotate to the left. The time complexity is @var{o}(n). @example @group (-rotate 3 '(1 2 3 4 5 6 7)) @result{} '(5 6 7 1 2 3 4) @end group @group (-rotate -3 '(1 2 3 4 5 6 7)) @result{} '(4 5 6 7 1 2 3) @end group @group (-rotate 16 '(1 2 3 4 5 6 7)) @result{} '(6 7 1 2 3 4 5) @end group @end example @end defun @anchor{-repeat} @defun -repeat (n x) Return a new list of length @var{n} with each element being @var{x}. Return nil if @var{n} is less than 1. @example @group (-repeat 3 :a) @result{} '(:a :a :a) @end group @group (-repeat 1 :a) @result{} '(:a) @end group @group (-repeat 0 :a) @result{} nil @end group @end example @end defun @anchor{-cons*} @defun -cons* (&rest args) Make a new list from the elements of @var{args}. The last 2 members of @var{args} are used as the final cons of the result so if the final member of @var{args} is not a list the result is a dotted list. @example @group (-cons* 1 2) @result{} '(1 . 2) @end group @group (-cons* 1 2 3) @result{} '(1 2 . 3) @end group @group (-cons* 1) @result{} 1 @end group @end example @end defun @anchor{-snoc} @defun -snoc (list elem &rest elements) Append @var{elem} to the end of the list. This is like @code{cons}, but operates on the end of list. If @var{elements} is non nil, append these to the list as well. @example @group (-snoc '(1 2 3) 4) @result{} '(1 2 3 4) @end group @group (-snoc '(1 2 3) 4 5 6) @result{} '(1 2 3 4 5 6) @end group @group (-snoc '(1 2 3) '(4 5 6)) @result{} '(1 2 3 (4 5 6)) @end group @end example @end defun @anchor{-interpose} @defun -interpose (sep list) Return a new list of all elements in @var{list} separated by @var{sep}. @example @group (-interpose "-" '()) @result{} '() @end group @group (-interpose "-" '("a")) @result{} '("a") @end group @group (-interpose "-" '("a" "b" "c")) @result{} '("a" "-" "b" "-" "c") @end group @end example @end defun @anchor{-interleave} @defun -interleave (&rest lists) Return a new list of the first item in each list, then the second etc. @example @group (-interleave '(1 2) '("a" "b")) @result{} '(1 "a" 2 "b") @end group @group (-interleave '(1 2) '("a" "b") '("A" "B")) @result{} '(1 "a" "A" 2 "b" "B") @end group @group (-interleave '(1 2 3) '("a" "b")) @result{} '(1 "a" 2 "b") @end group @end example @end defun @anchor{-zip-with} @defun -zip-with (fn list1 list2) Zip the two lists @var{list1} and @var{list2} using a function @var{fn}. This function is applied pairwise taking as first argument element of @var{list1} and as second argument element of @var{list2} at corresponding position. The anaphoric form @code{--zip-with} binds the elements from @var{list1} as symbol @code{it}, and the elements from @var{list2} as symbol @code{other}. @example @group (-zip-with '+ '(1 2 3) '(4 5 6)) @result{} '(5 7 9) @end group @group (-zip-with 'cons '(1 2 3) '(4 5 6)) @result{} '((1 . 4) (2 . 5) (3 . 6)) @end group @group (--zip-with (concat it " and " other) '("Batman" "Jekyll") '("Robin" "Hyde")) @result{} '("Batman and Robin" "Jekyll and Hyde") @end group @end example @end defun @anchor{-zip} @defun -zip (&rest lists) Zip @var{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 @code{-zip-lists} (@pxref{-zip-lists}) if you need the return value to always be a list of lists. Alias: @code{-zip-pair} See also: @code{-zip-lists} (@pxref{-zip-lists}) @example @group (-zip '(1 2 3) '(4 5 6)) @result{} '((1 . 4) (2 . 5) (3 . 6)) @end group @group (-zip '(1 2 3) '(4 5 6 7)) @result{} '((1 . 4) (2 . 5) (3 . 6)) @end group @group (-zip '(1 2) '(3 4 5) '(6)) @result{} '((1 3 6)) @end group @end example @end defun @anchor{-zip-lists} @defun -zip-lists (&rest lists) Zip @var{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 @code{-zip-pair} which returns a cons-cell in case two input lists are provided. See also: @code{-zip} (@pxref{-zip}) @example @group (-zip-lists '(1 2 3) '(4 5 6)) @result{} '((1 4) (2 5) (3 6)) @end group @group (-zip-lists '(1 2 3) '(4 5 6 7)) @result{} '((1 4) (2 5) (3 6)) @end group @group (-zip-lists '(1 2) '(3 4 5) '(6)) @result{} '((1 3 6)) @end group @end example @end defun @anchor{-zip-fill} @defun -zip-fill (fill-value &rest lists) Zip @var{lists}, with @var{fill-value} padded onto the shorter lists. The lengths of the returned groupings are equal to the length of the longest input list. @example @group (-zip-fill 0 '(1 2 3 4 5) '(6 7 8 9)) @result{} '((1 . 6) (2 . 7) (3 . 8) (4 . 9) (5 . 0)) @end group @end example @end defun @anchor{-unzip} @defun -unzip (lists) Unzip @var{lists}. This works just like @code{-zip} (@pxref{-zip}) but takes a list of lists instead of a variable number of arguments, such that (-unzip (-zip @var{l1} @var{l2} @var{l3} @dots{})) 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: @code{-zip} (@pxref{-zip}) @example @group (-unzip (-zip '(1 2 3) '(a b c) '("e" "f" "g"))) @result{} '((1 2 3) (a b c) ("e" "f" "g")) @end group @group (-unzip '((1 2) (3 4) (5 6) (7 8) (9 10))) @result{} '((1 3 5 7 9) (2 4 6 8 10)) @end group @group (-unzip '((1 2) (3 4))) @result{} '((1 . 3) (2 . 4)) @end group @end example @end defun @anchor{-cycle} @defun -cycle (list) Return an infinite circular copy of @var{list}. The returned list cycles through the elements of @var{list} and repeats from the beginning. @example @group (-take 5 (-cycle '(1 2 3))) @result{} '(1 2 3 1 2) @end group @group (-take 7 (-cycle '(1 "and" 3))) @result{} '(1 "and" 3 1 "and" 3 1) @end group @group (-zip (-cycle '(1 2 3)) '(1 2)) @result{} '((1 . 1) (2 . 2)) @end group @end example @end defun @anchor{-pad} @defun -pad (fill-value &rest lists) Appends @var{fill-value} to the end of each list in @var{lists} such that they will all have the same length. @example @group (-pad 0 '()) @result{} '(nil) @end group @group (-pad 0 '(1)) @result{} '((1)) @end group @group (-pad 0 '(1 2 3) '(4 5)) @result{} '((1 2 3) (4 5 0)) @end group @end example @end defun @anchor{-table} @defun -table (fn &rest lists) Compute outer product of @var{lists} using function @var{fn}. The function @var{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: @code{-table-flat} (@pxref{-table-flat}) @example @group (-table '* '(1 2 3) '(1 2 3)) @result{} '((1 2 3) (2 4 6) (3 6 9)) @end group @group (-table (lambda (a b) (-sum (-zip-with '* a b))) '((1 2) (3 4)) '((1 3) (2 4))) @result{} '((7 15) (10 22)) @end group @group (apply '-table 'list (-repeat 3 '(1 2))) @result{} '((((1 1 1) (2 1 1)) ((1 2 1) (2 2 1))) (((1 1 2) (2 1 2)) ((1 2 2) (2 2 2)))) @end group @end example @end defun @anchor{-table-flat} @defun -table-flat (fn &rest lists) Compute flat outer product of @var{lists} using function @var{fn}. The function @var{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: @code{-flatten-n} (@pxref{-flatten-n}), @code{-table} (@pxref{-table}) @example @group (-table-flat 'list '(1 2 3) '(a b c)) @result{} '((1 a) (2 a) (3 a) (1 b) (2 b) (3 b) (1 c) (2 c) (3 c)) @end group @group (-table-flat '* '(1 2 3) '(1 2 3)) @result{} '(1 2 3 2 4 6 3 6 9) @end group @group (apply '-table-flat 'list (-repeat 3 '(1 2))) @result{} '((1 1 1) (2 1 1) (1 2 1) (2 2 1) (1 1 2) (2 1 2) (1 2 2) (2 2 2)) @end group @end example @end defun @anchor{-first} @defun -first (pred list) Return the first x in @var{list} where (@var{pred} x) is non-nil, else nil. To get the first item in the list no questions asked, use @code{car}. Alias: @code{-find} @example @group (-first 'even? '(1 2 3)) @result{} 2 @end group @group (-first 'even? '(1 3 5)) @result{} nil @end group @group (-first 'null '(1 3 5)) @result{} nil @end group @end example @end defun @anchor{-some} @defun -some (pred list) Return (@var{pred} x) for the first @var{list} item where (@var{pred} x) is non-nil, else nil. Alias: @code{-any} @example @group (-some 'even? '(1 2 3)) @result{} t @end group @group (-some 'null '(1 2 3)) @result{} nil @end group @group (-some 'null '(1 2 nil)) @result{} t @end group @end example @end defun @anchor{-last} @defun -last (pred list) Return the last x in @var{list} where (@var{pred} x) is non-nil, else nil. @example @group (-last 'even? '(1 2 3 4 5 6 3 3 3)) @result{} 6 @end group @group (-last 'even? '(1 3 7 5 9)) @result{} nil @end group @group (--last (> (length it) 3) '("a" "looong" "word" "and" "short" "one")) @result{} "short" @end group @end example @end defun @anchor{-first-item} @defun -first-item (list) Return the first item of @var{list}, or nil on an empty list. See also: @code{-second-item} (@pxref{-second-item}), @code{-last-item} (@pxref{-last-item}). (fn @var{list}) @example @group (-first-item '(1 2 3)) @result{} 1 @end group @group (-first-item nil) @result{} nil @end group @group (let ((list (list 1 2 3))) (setf (-first-item list) 5) list) @result{} '(5 2 3) @end group @end example @end defun @anchor{-second-item} @defun -second-item (arg1) Return the second item of @var{list}, or nil if @var{list} is too short. See also: @code{-third-item} (@pxref{-third-item}). (fn @var{list}) @example @group (-second-item '(1 2 3)) @result{} 2 @end group @group (-second-item nil) @result{} nil @end group @end example @end defun @anchor{-third-item} @defun -third-item (arg1) Return the third item of @var{list}, or nil if @var{list} is too short. See also: @code{-fourth-item} (@pxref{-fourth-item}). (fn @var{list}) @example @group (-third-item '(1 2 3)) @result{} 3 @end group @group (-third-item nil) @result{} nil @end group @end example @end defun @anchor{-fourth-item} @defun -fourth-item (list) Return the fourth item of @var{list}, or nil if @var{list} is too short. See also: @code{-fifth-item} (@pxref{-fifth-item}). @example @group (-fourth-item '(1 2 3 4)) @result{} 4 @end group @group (-fourth-item nil) @result{} nil @end group @end example @end defun @anchor{-fifth-item} @defun -fifth-item (list) Return the fifth item of @var{list}, or nil if @var{list} is too short. See also: @code{-last-item} (@pxref{-last-item}). @example @group (-fifth-item '(1 2 3 4 5)) @result{} 5 @end group @group (-fifth-item nil) @result{} nil @end group @end example @end defun @anchor{-last-item} @defun -last-item (list) Return the last item of @var{list}, or nil on an empty list. @example @group (-last-item '(1 2 3)) @result{} 3 @end group @group (-last-item nil) @result{} nil @end group @group (let ((list (list 1 2 3))) (setf (-last-item list) 5) list) @result{} '(1 2 5) @end group @end example @end defun @anchor{-butlast} @defun -butlast (list) Return a list of all items in list except for the last. @example @group (-butlast '(1 2 3)) @result{} '(1 2) @end group @group (-butlast '(1 2)) @result{} '(1) @end group @group (-butlast '(1)) @result{} nil @end group @end example @end defun @anchor{-sort} @defun -sort (comparator list) Sort @var{list}, stably, comparing elements using @var{comparator}. Return the sorted list. @var{list} is @var{not} modified by side effects. @var{comparator} is called with two elements of @var{list}, and should return non-nil if the first element should sort before the second. @example @group (-sort '< '(3 1 2)) @result{} '(1 2 3) @end group @group (-sort '> '(3 1 2)) @result{} '(3 2 1) @end group @group (--sort (< it other) '(3 1 2)) @result{} '(1 2 3) @end group @end example @end defun @anchor{-list} @defun -list (&rest args) Return a list with @var{args}. If first item of @var{args} is already a list, simply return @var{args}. If not, return a list with @var{args} as elements. @example @group (-list 1) @result{} '(1) @end group @group (-list 1 2 3) @result{} '(1 2 3) @end group @group (-list '(1 2 3)) @result{} '(1 2 3) @end group @end example @end defun @anchor{-fix} @defun -fix (fn list) Compute the (least) fixpoint of @var{fn} with initial input @var{list}. @var{fn} is called at least once, results are compared with @code{equal}. @example @group (-fix (lambda (l) (-non-nil (--mapcat (-split-at (/ (length it) 2) it) l))) '((1 2 3 4 5 6))) @result{} '((1) (2) (3) (4) (5) (6)) @end group @group (let ((data '(("starwars" "scifi") ("jedi" "starwars" "warrior")))) (--fix (-uniq (--mapcat (cons it (cdr (assoc it data))) it)) '("jedi" "book"))) @result{} '("jedi" "starwars" "warrior" "scifi" "book") @end group @end example @end defun @node Tree operations @section Tree operations Functions pretending lists are trees. @anchor{-tree-seq} @defun -tree-seq (branch children tree) Return a sequence of the nodes in @var{tree}, in depth-first search order. @var{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. @var{children} is a function of one argument that returns the children of the passed branch node. Non-branch nodes are simply copied. @example @group (-tree-seq 'listp 'identity '(1 (2 3) 4 (5 (6 7)))) @result{} '((1 (2 3) 4 (5 (6 7))) 1 (2 3) 2 3 4 (5 (6 7)) 5 (6 7) 6 7) @end group @group (-tree-seq 'listp 'reverse '(1 (2 3) 4 (5 (6 7)))) @result{} '((1 (2 3) 4 (5 (6 7))) (5 (6 7)) (6 7) 7 6 5 4 (2 3) 3 2 1) @end group @group (--tree-seq (vectorp it) (append it nil) [1 [2 3] 4 [5 [6 7]]]) @result{} '([1 [2 3] 4 [5 [6 7]]] 1 [2 3] 2 3 4 [5 [6 7]] 5 [6 7] 6 7) @end group @end example @end defun @anchor{-tree-map} @defun -tree-map (fn tree) Apply @var{fn} to each element of @var{tree} while preserving the tree structure. @example @group (-tree-map '1+ '(1 (2 3) (4 (5 6) 7))) @result{} '(2 (3 4) (5 (6 7) 8)) @end group @group (-tree-map '(lambda (x) (cons x (expt 2 x))) '(1 (2 3) 4)) @result{} '((1 . 2) ((2 . 4) (3 . 8)) (4 . 16)) @end group @group (--tree-map (length it) '("" ("

" "text" "

") "")) @result{} '(6 (3 4 4) 7) @end group @end example @end defun @anchor{-tree-map-nodes} @defun -tree-map-nodes (pred fun tree) Call @var{fun} on each node of @var{tree} that satisfies @var{pred}. If @var{pred} returns nil, continue descending down this node. If @var{pred} returns non-nil, apply @var{fun} to this node and do not descend further. @example @group (-tree-map-nodes 'vectorp (lambda (x) (-sum (append x nil))) '(1 [2 3] 4 (5 [6 7] 8))) @result{} '(1 5 4 (5 13 8)) @end group @group (-tree-map-nodes 'keywordp (lambda (x) (symbol-name x)) '(1 :foo 4 ((5 6 :bar) :baz 8))) @result{} '(1 ":foo" 4 ((5 6 ":bar") ":baz" 8)) @end group @group (--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)))) @result{} '(with-mode emacs-lisp-mode (foo bar) (add-mode a b :mode emacs-lisp-mode) (baz (add-mode c d :mode emacs-lisp-mode))) @end group @end example @end defun @anchor{-tree-reduce} @defun -tree-reduce (fn tree) Use @var{fn} to reduce elements of list @var{tree}. If elements of @var{tree} are lists themselves, apply the reduction recursively. @var{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 @code{-reduce-r} (@pxref{-reduce-r}) for how exactly are lists of zero or one element handled. @example @group (-tree-reduce '+ '(1 (2 3) (4 5))) @result{} 15 @end group @group (-tree-reduce 'concat '("strings" (" on" " various") ((" levels")))) @result{} "strings on various levels" @end group @group (--tree-reduce (cond ((stringp it) (concat it " " acc)) (t (let ((sn (symbol-name it))) (concat "<" sn ">" acc "")))) '(body (p "some words") (div "more" (b "bold") "words"))) @result{} "

some words

more bold words
" @end group @end example @end defun @anchor{-tree-reduce-from} @defun -tree-reduce-from (fn init-value tree) Use @var{fn} to reduce elements of list @var{tree}. If elements of @var{tree} are lists themselves, apply the reduction recursively. @var{fn} is first applied to @var{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. @example @group (-tree-reduce-from '+ 1 '(1 (1 1) ((1)))) @result{} 8 @end group @group (--tree-reduce-from (-concat acc (list it)) nil '(1 (2 3 (4 5)) (6 7))) @result{} '((7 6) ((5 4) 3 2) 1) @end group @end example @end defun @anchor{-tree-mapreduce} @defun -tree-mapreduce (fn folder tree) Apply @var{fn} to each element of @var{tree}, and make a list of the results. If elements of @var{tree} are lists themselves, apply @var{fn} recursively to elements of these nested lists. Then reduce the resulting lists using @var{folder} and initial value @var{init-value}. See @code{-reduce-r-from} (@pxref{-reduce-r-from}). This is the same as calling @code{-tree-reduce} (@pxref{-tree-reduce}) after @code{-tree-map} (@pxref{-tree-map}) but is twice as fast as it only traverse the structure once. @example @group (-tree-mapreduce 'list 'append '(1 (2 (3 4) (5 6)) (7 (8 9)))) @result{} '(1 2 3 4 5 6 7 8 9) @end group @group (--tree-mapreduce 1 (+ it acc) '(1 (2 (4 9) (2 1)) (7 (4 3)))) @result{} 9 @end group @group (--tree-mapreduce 0 (max acc (1+ it)) '(1 (2 (4 9) (2 1)) (7 (4 3)))) @result{} 3 @end group @end example @end defun @anchor{-tree-mapreduce-from} @defun -tree-mapreduce-from (fn folder init-value tree) Apply @var{fn} to each element of @var{tree}, and make a list of the results. If elements of @var{tree} are lists themselves, apply @var{fn} recursively to elements of these nested lists. Then reduce the resulting lists using @var{folder} and initial value @var{init-value}. See @code{-reduce-r-from} (@pxref{-reduce-r-from}). This is the same as calling @code{-tree-reduce-from} (@pxref{-tree-reduce-from}) after @code{-tree-map} (@pxref{-tree-map}) but is twice as fast as it only traverse the structure once. @example @group (-tree-mapreduce-from 'identity '* 1 '(1 (2 (3 4) (5 6)) (7 (8 9)))) @result{} 362880 @end group @group (--tree-mapreduce-from (+ it it) (cons it acc) nil '(1 (2 (4 9) (2 1)) (7 (4 3)))) @result{} '(2 (4 (8 18) (4 2)) (14 (8 6))) @end group @group (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) "@}" '((elips-mode (foo (bar . booze)) (baz . qux)) (c-mode (foo . bla) (bum . bam))))) @result{} "@{elips-mode : @{foo : @{bar -> booze@{, baz -> qux@{, c-mode : @{foo -> bla, bum -> bam@}@}" @end group @end example @end defun @anchor{-clone} @defun -clone (list) Create a deep copy of @var{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. @example @group (let* ((a '(1 2 3)) (b (-clone a))) (nreverse a) b) @result{} '(1 2 3) @end group @end example @end defun @node Threading macros @section Threading macros @anchor{->} @defmac -> (x &optional form &rest more) Thread the expr through the forms. Insert @var{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. @example @group (-> '(2 3 5)) @result{} '(2 3 5) @end group @group (-> '(2 3 5) (append '(8 13))) @result{} '(2 3 5 8 13) @end group @group (-> '(2 3 5) (append '(8 13)) (-slice 1 -1)) @result{} '(3 5 8) @end group @end example @end defmac @anchor{->>} @defmac ->> (x &optional form &rest more) Thread the expr through the forms. Insert @var{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. @example @group (->> '(1 2 3) (-map 'square)) @result{} '(1 4 9) @end group @group (->> '(1 2 3) (-map 'square) (-remove 'even?)) @result{} '(1 9) @end group @group (->> '(1 2 3) (-map 'square) (-reduce '+)) @result{} 14 @end group @end example @end defmac @anchor{-->} @defmac --> (x &rest forms) Starting with the value of @var{x}, thread each expression through @var{forms}. Insert @var{x} at the position signified by the symbol @code{it} in the first form. If there are more forms, insert the first form at the position signified by @code{it} in in second form, etc. @example @group (--> "def" (concat "abc" it "ghi")) @result{} "abcdefghi" @end group @group (--> "def" (concat "abc" it "ghi") (upcase it)) @result{} "ABCDEFGHI" @end group @group (--> "def" (concat "abc" it "ghi") upcase) @result{} "ABCDEFGHI" @end group @end example @end defmac @anchor{-as->} @defmac -as-> (value variable &rest forms) Starting with @var{value}, thread @var{variable} through @var{forms}. In the first form, bind @var{variable} to @var{value}. In the second form, bind @var{variable} to the result of the first form, and so forth. @example @group (-as-> 3 my-var (1+ my-var) (list my-var) (mapcar (lambda (ele) (* 2 ele)) my-var)) @result{} '(8) @end group @group (-as-> 3 my-var 1+) @result{} 4 @end group @group (-as-> 3 my-var) @result{} 3 @end group @end example @end defmac @anchor{-some->} @defmac -some-> (x &optional form &rest more) When expr is non-nil, thread it through the first form (via @code{->} (@pxref{->})), and when that result is non-nil, through the next form, etc. @example @group (-some-> '(2 3 5)) @result{} '(2 3 5) @end group @group (-some-> 5 square) @result{} 25 @end group @group (-some-> 5 even? square) @result{} nil @end group @end example @end defmac @anchor{-some->>} @defmac -some->> (x &optional form &rest more) When expr is non-nil, thread it through the first form (via @code{->>} (@pxref{->>})), and when that result is non-nil, through the next form, etc. @example @group (-some->> '(1 2 3) (-map 'square)) @result{} '(1 4 9) @end group @group (-some->> '(1 3 5) (-last 'even?) (+ 100)) @result{} nil @end group @group (-some->> '(2 4 6) (-last 'even?) (+ 100)) @result{} 106 @end group @end example @end defmac @anchor{-some-->} @defmac -some--> (x &optional form &rest more) When expr is non-nil, thread it through the first form (via @code{-->} (@pxref{-->})), and when that result is non-nil, through the next form, etc. @example @group (-some--> "def" (concat "abc" it "ghi")) @result{} "abcdefghi" @end group @group (-some--> nil (concat "abc" it "ghi")) @result{} nil @end group @group (-some--> '(1 3 5) (-filter 'even? it) (append it it) (-map 'square it)) @result{} nil @end group @end example @end defmac @node Binding @section Binding Convenient versions of `let` and `let*` constructs combined with flow control. @anchor{-when-let} @defmac -when-let (var-val &rest body) If @var{val} evaluates to non-nil, bind it to @var{var} and execute body. Note: binding is done according to @code{-let} (@pxref{-let}). (fn (@var{var} @var{val}) &rest @var{body}) @example @group (-when-let (match-index (string-match "d" "abcd")) (+ match-index 2)) @result{} 5 @end group @group (-when-let ((&plist :foo foo) (list :foo "foo")) foo) @result{} "foo" @end group @group (-when-let ((&plist :foo foo) (list :bar "bar")) foo) @result{} nil @end group @end example @end defmac @anchor{-when-let*} @defmac -when-let* (vars-vals &rest body) If all @var{vals} evaluate to true, bind them to their corresponding @var{vars} and execute body. @var{vars-vals} should be a list of (@var{var} @var{val}) pairs. Note: binding is done according to @code{-let*} (@pxref{-let*}). @var{vals} are evaluated sequentially, and evaluation stops after the first nil @var{val} is encountered. @example @group (-when-let* ((x 5) (y 3) (z (+ y 4))) (+ x y z)) @result{} 15 @end group @group (-when-let* ((x 5) (y nil) (z 7)) (+ x y z)) @result{} nil @end group @end example @end defmac @anchor{-if-let} @defmac -if-let (var-val then &rest else) If @var{val} evaluates to non-nil, bind it to @var{var} and do @var{then}, otherwise do @var{else}. Note: binding is done according to @code{-let} (@pxref{-let}). (fn (@var{var} @var{val}) @var{then} &rest @var{else}) @example @group (-if-let (match-index (string-match "d" "abc")) (+ match-index 3) 7) @result{} 7 @end group @group (--if-let (even? 4) it nil) @result{} t @end group @end example @end defmac @anchor{-if-let*} @defmac -if-let* (vars-vals then &rest else) If all @var{vals} evaluate to true, bind them to their corresponding @var{vars} and do @var{then}, otherwise do @var{else}. @var{vars-vals} should be a list of (@var{var} @var{val}) pairs. Note: binding is done according to @code{-let*} (@pxref{-let*}). @var{vals} are evaluated sequentially, and evaluation stops after the first nil @var{val} is encountered. @example @group (-if-let* ((x 5) (y 3) (z 7)) (+ x y z) "foo") @result{} 15 @end group @group (-if-let* ((x 5) (y nil) (z 7)) (+ x y z) "foo") @result{} "foo" @end group @group (-if-let* (((_ _ x) '(nil nil 7))) x) @result{} 7 @end group @end example @end defmac @anchor{-let} @defmac -let (varlist &rest body) Bind variables according to @var{varlist} then eval @var{body}. @var{varlist} is a list of lists of the form (@var{pattern} @var{source}). Each @var{pattern} is matched against the @var{source} "structurally". @var{source} is only evaluated once for each @var{pattern}. Each @var{pattern} is matched recursively, and can therefore contain sub-patterns which are matched against corresponding sub-expressions of @var{source}. All the SOURCEs are evalled before any symbols are bound (i.e. "in parallel"). If @var{varlist} only contains one (@var{pattern} @var{source}) element, you can optionally specify it using a vector and discarding the outer-most parens. Thus (-let ((@var{pattern} @var{source})) @dots{}) becomes (-let [@var{pattern} @var{source}] @dots{}). @code{-let} (@pxref{-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 @var{source} to @var{a}. This is just like regular @code{let}. Conses and lists: (a) - bind @code{car} of cons/list to @var{a} (a . b) - bind car of cons to @var{a} and @code{cdr} to @var{b} (a b) - bind car of list to @var{a} and @code{cadr} to @var{b} (a1 a2 a3 @dots{}) - bind 0th car of list to @var{a1}, 1st to @var{a2}, 2nd to @var{a3}@enddots{} (a1 a2 a3 @dots{} aN . rest) - as above, but bind the Nth cdr to @var{rest}. Vectors: [a] - bind 0th element of a non-list sequence to @var{a} (works with vectors, strings, bit arrays@dots{}) [a1 a2 a3 @dots{}] - bind 0th element of non-list sequence to @var{a0}, 1st to @var{a1}, 2nd to @var{a2}, @enddots{} If the @var{pattern} is shorter than @var{source}, the values at places not in @var{pattern} are ignored. If the @var{pattern} is longer than @var{source}, an @code{error} is thrown. [a1 a2 a3 @dots{} &rest rest] - as above, but bind the rest of the sequence to @var{rest}. This is conceptually the same as improper list matching (a1 a2 @dots{} aN . rest) Key/value stores: (&plist key0 a0 @dots{} keyN aN) - bind value mapped by keyK in the @var{source} plist to aK. If the value is not found, aK is nil. Uses @code{plist-get} to fetch values. (&alist key0 a0 @dots{} keyN aN) - bind value mapped by keyK in the @var{source} alist to aK. If the value is not found, aK is nil. Uses @code{assoc} to fetch values. (&hash key0 a0 @dots{} keyN aN) - bind value mapped by keyK in the @var{source} hash table to aK. If the value is not found, aK is nil. Uses @code{gethash} to fetch values. Further, special keyword &keys supports "inline" matching of plist-like key-value pairs, similarly to &keys keyword of @code{cl-defun}. (a1 a2 @dots{} aN &keys key1 b1 @dots{} keyN bK) This binds @var{n} values from the list to a1 @dots{} aN, then interprets the cdr as a plist (see key/value matching above). @var{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 @code{foo} pattern, - a key 'bar is converted into @code{bar} pattern, - a key "baz" is converted into @code{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 @var{symbol} &as @var{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 @var{a} to 1, @var{b} to 2, @var{c} to 3 and @var{list} to (1 2 3). Similarly: (bounds &as beg . end) (cons 1 2) binds @var{beg} to 1, @var{end} to 2 and @var{bounds} to (1 . 2). (items &as first . rest) (list 1 2 3) binds @var{first} to 1, @var{rest} to (2 3) and @var{items} to (1 2 3) [vect &as _ b c] [1 2 3] binds @var{b} to 2, @var{c} to 3 and @var{vect} to [1 2 3] (_ avoids binding as usual). (plist &as &plist :b b) (list :a 1 :b 2 :c 3) binds @var{b} to 2 and @var{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. @example @group (-let (([a (b c) d] [1 (2 3) 4])) (list a b c d)) @result{} '(1 2 3 4) @end group @group (-let [(a b c . d) (list 1 2 3 4 5 6)] (list a b c d)) @result{} '(1 2 3 (4 5 6)) @end group @group (-let [(&plist :foo foo :bar bar) (list :baz 3 :foo 1 :qux 4 :bar 2)] (list foo bar)) @result{} '(1 2) @end group @end example @end defmac @anchor{-let*} @defmac -let* (varlist &rest body) Bind variables according to @var{varlist} then eval @var{body}. @var{varlist} is a list of lists of the form (@var{pattern} @var{source}). Each @var{pattern} is matched against the @var{source} structurally. @var{source} is only evaluated once for each @var{pattern}. Each @var{source} can refer to the symbols already bound by this @var{varlist}. This is useful if you want to destructure @var{source} recursively but also want to name the intermediate structures. See @code{-let} (@pxref{-let}) for the list of all possible patterns. @example @group (-let* (((a . b) (cons 1 2)) ((c . d) (cons 3 4))) (list a b c d)) @result{} '(1 2 3 4) @end group @group (-let* (((a . b) (cons 1 (cons 2 3))) ((c . d) b)) (list a b c d)) @result{} '(1 (2 . 3) 2 3) @end group @group (-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)) @result{} '(1 a b c (a b c)) @end group @end example @end defmac @anchor{-lambda} @defmac -lambda (match-form &rest body) Return a lambda which destructures its input as @var{match-form} and executes @var{body}. Note that you have to enclose the @var{match-form} in a pair of parens, such that: (-lambda (x) body) (-lambda (x y @dots{}) body) has the usual semantics of @code{lambda}. Furthermore, these get translated into normal lambda, so there is no performance penalty. See @code{-let} (@pxref{-let}) for the description of destructuring mechanism. @example @group (-map (-lambda ((x y)) (+ x y)) '((1 2) (3 4) (5 6))) @result{} '(3 7 11) @end group @group (-map (-lambda ([x y]) (+ x y)) '([1 2] [3 4] [5 6])) @result{} '(3 7 11) @end group @group (funcall (-lambda ((_ . a) (_ . b)) (-concat a b)) '(1 2 3) '(4 5 6)) @result{} '(2 3 5 6) @end group @end example @end defmac @anchor{-setq} @defmac -setq (&rest forms) Bind each @var{match-form} to the value of its @var{val}. @var{match-form} destructuring is done according to the rules of @code{-let} (@pxref{-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 @var{val} once so that in case of multiple assignments it does not cause unexpected side effects. (fn [@var{match-form} @var{val}]@dots{}) @example @group (progn (-setq a 1) a) @result{} 1 @end group @group (progn (-setq (a b) (list 1 2)) (list a b)) @result{} '(1 2) @end group @group (progn (-setq (&plist :c c) (list :c "c")) c) @result{} "c" @end group @end example @end defmac @node Side-effects @section Side-effects Functions iterating over lists for side-effect only. @anchor{-each} @defun -each (list fn) Call @var{fn} with every item in @var{list}. Return nil, used for side-effects only. @example @group (let (s) (-each '(1 2 3) (lambda (item) (setq s (cons item s))))) @result{} nil @end group @group (let (s) (-each '(1 2 3) (lambda (item) (setq s (cons item s)))) s) @result{} '(3 2 1) @end group @group (let (s) (--each '(1 2 3) (setq s (cons it s))) s) @result{} '(3 2 1) @end group @end example @end defun @anchor{-each-while} @defun -each-while (list pred fn) Call @var{fn} with every item in @var{list} while (@var{pred} item) is non-nil. Return nil, used for side-effects only. @example @group (let (s) (-each-while '(2 4 5 6) 'even? (lambda (item) (push item s))) s) @result{} '(4 2) @end group @group (let (s) (--each-while '(1 2 3 4) (< it 3) (push it s)) s) @result{} '(2 1) @end group @group (let ((s 0)) (--each-while '(1 3 4 5) (odd? it) (setq s (+ s it))) s) @result{} 4 @end group @end example @end defun @anchor{-each-indexed} @defun -each-indexed (list fn) Call (@var{fn} index item) for each item in @var{list}. In the anaphoric form @code{--each-indexed}, the index is exposed as symbol @code{it-index}. See also: @code{-map-indexed} (@pxref{-map-indexed}). @example @group (let (s) (-each-indexed '(a b c) (lambda (index item) (setq s (cons (list item index) s)))) s) @result{} '((c 2) (b 1) (a 0)) @end group @group (let (s) (--each-indexed '(a b c) (setq s (cons (list it it-index) s))) s) @result{} '((c 2) (b 1) (a 0)) @end group @end example @end defun @anchor{-each-r} @defun -each-r (list fn) Call @var{fn} with every item in @var{list} in reversed order. Return nil, used for side-effects only. @example @group (let (s) (-each-r '(1 2 3) (lambda (item) (setq s (cons item s))))) @result{} nil @end group @group (let (s) (-each-r '(1 2 3) (lambda (item) (setq s (cons item s)))) s) @result{} '(1 2 3) @end group @group (let (s) (--each-r '(1 2 3) (setq s (cons it s))) s) @result{} '(1 2 3) @end group @end example @end defun @anchor{-each-r-while} @defun -each-r-while (list pred fn) Call @var{fn} with every item in reversed @var{list} while (@var{pred} item) is non-nil. Return nil, used for side-effects only. @example @group (let (s) (-each-r-while '(2 4 5 6) 'even? (lambda (item) (!cons item s))) s) @result{} '(6) @end group @group (let (s) (--each-r-while '(1 2 3 4) (>= it 3) (!cons it s)) s) @result{} '(3 4) @end group @end example @end defun @anchor{-dotimes} @defun -dotimes (num fn) Call @var{fn} @var{num} times, presumably for side-effects. @var{fn} is called with a single argument on successive integers running from 0, inclusive, to @var{num}, exclusive. @var{fn} is not called if @var{num} is less than 1. @example @group (let (s) (-dotimes 3 (lambda (n) (push n s))) s) @result{} '(2 1 0) @end group @group (let (s) (-dotimes 0 (lambda (n) (push n s))) s) @result{} nil @end group @group (let (s) (--dotimes 5 (push it s)) s) @result{} '(4 3 2 1 0) @end group @end example @end defun @anchor{-doto} @defmac -doto (eval-initial-value &rest forms) Eval a form, then insert that form as the 2nd argument to other forms. The @var{eval-initial-value} form is evaluated once. Its result is passed to @var{forms}, which are then evaluated sequentially. Returns the target form. @example @group (-doto '(1 2 3) (!cdr) (!cdr)) @result{} '(3) @end group @group (-doto '(1 . 2) (setcar 3) (setcdr 4)) @result{} '(3 . 4) @end group @end example @end defmac @anchor{--doto} @defmac --doto (eval-initial-value &rest forms) Anaphoric form of @code{-doto} (@pxref{-doto}). Note: @code{it} is not required in each form. @example @group (gethash "key" (--doto (make-hash-table :test 'equal) (puthash "key" "value" it))) @result{} "value" @end group @end example @end defmac @node Destructive operations @section Destructive operations @anchor{!cons} @defmac !cons (car cdr) Destructive: Set @var{cdr} to the cons of @var{car} and @var{cdr}. @example @group (let (l) (!cons 5 l) l) @result{} '(5) @end group @group (let ((l '(3))) (!cons 5 l) l) @result{} '(5 3) @end group @end example @end defmac @anchor{!cdr} @defmac !cdr (list) Destructive: Set @var{list} to the cdr of @var{list}. @example @group (let ((l '(3))) (!cdr l) l) @result{} '() @end group @group (let ((l '(3 5))) (!cdr l) l) @result{} '(5) @end group @end example @end defmac @node Function combinators @section Function combinators These combinators require Emacs 24 for its lexical scope. So they are offered in a separate package: `dash-functional`. @anchor{-partial} @defun -partial (fn &rest args) Take a function @var{fn} and fewer than the normal arguments to @var{fn}, and return a fn that takes a variable number of additional @var{args}. When called, the returned function calls @var{fn} with @var{args} first and then additional args. @example @group (funcall (-partial '- 5) 3) @result{} 2 @end group @group (funcall (-partial '+ 5 2) 3) @result{} 10 @end group @end example @end defun @anchor{-rpartial} @defun -rpartial (fn &rest args) Takes a function @var{fn} and fewer than the normal arguments to @var{fn}, and returns a fn that takes a variable number of additional @var{args}. When called, the returned function calls @var{fn} with the additional args first and then @var{args}. @example @group (funcall (-rpartial '- 5) 8) @result{} 3 @end group @group (funcall (-rpartial '- 5 2) 10) @result{} 3 @end group @end example @end defun @anchor{-juxt} @defun -juxt (&rest fns) Takes a list of functions and returns a fn that is the juxtaposition of those fns. The returned fn takes a variable number of args, and returns a list containing the result of applying each fn to the args (left-to-right). @example @group (funcall (-juxt '+ '-) 3 5) @result{} '(8 -2) @end group @group (-map (-juxt 'identity 'square) '(1 2 3)) @result{} '((1 1) (2 4) (3 9)) @end group @end example @end defun @anchor{-compose} @defun -compose (&rest fns) Takes a list of functions and returns a fn that is the composition of those fns. The returned fn takes a variable number of arguments, and returns the result of applying each fn to the result of applying the previous fn to the arguments (right-to-left). @example @group (funcall (-compose 'square '+) 2 3) @result{} (square (+ 2 3)) @end group @group (funcall (-compose 'identity 'square) 3) @result{} (square 3) @end group @group (funcall (-compose 'square 'identity) 3) @result{} (square 3) @end group @end example @end defun @anchor{-applify} @defun -applify (fn) Changes an n-arity function @var{fn} to a 1-arity function that expects a list with n items as arguments @example @group (-map (-applify '+) '((1 1 1) (1 2 3) (5 5 5))) @result{} '(3 6 15) @end group @group (-map (-applify (lambda (a b c) `(,a (,b (,c))))) '((1 1 1) (1 2 3) (5 5 5))) @result{} '((1 (1 (1))) (1 (2 (3))) (5 (5 (5)))) @end group @group (funcall (-applify '<) '(3 6)) @result{} t @end group @end example @end defun @anchor{-on} @defun -on (operator transformer) Return a function of two arguments that first applies @var{transformer} to each of them and then applies @var{operator} on the results (in the same order). In types: (b -> b -> c) -> (a -> b) -> a -> a -> c @example @group (-sort (-on '< 'length) '((1 2 3) (1) (1 2))) @result{} '((1) (1 2) (1 2 3)) @end group @group (-min-by (-on '> 'length) '((1 2 3) (4) (1 2))) @result{} '(4) @end group @group (-min-by (-on 'string-lessp 'number-to-string) '(2 100 22)) @result{} 22 @end group @end example @end defun @anchor{-flip} @defun -flip (func) Swap the order of arguments for binary function @var{func}. In types: (a -> b -> c) -> b -> a -> c @example @group (funcall (-flip '<) 2 1) @result{} t @end group @group (funcall (-flip '-) 3 8) @result{} 5 @end group @group (-sort (-flip '<) '(4 3 6 1)) @result{} '(6 4 3 1) @end group @end example @end defun @anchor{-const} @defun -const (c) Return a function that returns @var{c} ignoring any additional arguments. In types: a -> b -> a @example @group (funcall (-const 2) 1 3 "foo") @result{} 2 @end group @group (-map (-const 1) '("a" "b" "c" "d")) @result{} '(1 1 1 1) @end group @group (-sum (-map (-const 1) '("a" "b" "c" "d"))) @result{} 4 @end group @end example @end defun @anchor{-cut} @defmac -cut (&rest params) Take n-ary function and n arguments and specialize some of them. Arguments denoted by <> will be left unspecialized. See @var{srfi-26} for detailed description. @example @group (funcall (-cut list 1 <> 3 <> 5) 2 4) @result{} '(1 2 3 4 5) @end group @group (-map (-cut funcall <> 5) '(1+ 1- (lambda (x) (/ 1.0 x)))) @result{} '(6 4 0.2) @end group @group (-map (-cut <> 1 2 3) (list 'list 'vector 'string)) @result{} '((1 2 3) [1 2 3] "") @end group @end example @end defmac @anchor{-not} @defun -not (pred) Take a unary predicate @var{pred} and return a unary predicate that returns t if @var{pred} returns nil and nil if @var{pred} returns non-nil. @example @group (funcall (-not 'even?) 5) @result{} t @end group @group (-filter (-not (-partial '< 4)) '(1 2 3 4 5 6 7 8)) @result{} '(1 2 3 4) @end group @end example @end defun @anchor{-orfn} @defun -orfn (&rest preds) Take list of unary predicates @var{preds} and return a unary predicate with argument x that returns non-nil if at least one of the @var{preds} returns non-nil on x. In types: [a -> Bool] -> a -> Bool @example @group (-filter (-orfn 'even? (-partial (-flip '<) 5)) '(1 2 3 4 5 6 7 8 9 10)) @result{} '(1 2 3 4 6 8 10) @end group @group (funcall (-orfn 'stringp 'even?) "foo") @result{} t @end group @end example @end defun @anchor{-andfn} @defun -andfn (&rest preds) Take list of unary predicates @var{preds} and return a unary predicate with argument x that returns non-nil if all of the @var{preds} returns non-nil on x. In types: [a -> Bool] -> a -> Bool @example @group (funcall (-andfn (-cut < <> 10) 'even?) 6) @result{} t @end group @group (funcall (-andfn (-cut < <> 10) 'even?) 12) @result{} nil @end group @group (-filter (-andfn (-not 'even?) (-cut >= 5 <>)) '(1 2 3 4 5 6 7 8 9 10)) @result{} '(1 3 5) @end group @end example @end defun @anchor{-iteratefn} @defun -iteratefn (fn n) Return a function @var{fn} composed @var{n} times with itself. @var{fn} is a unary function. If you need to use a function of higher arity, use @code{-applify} (@pxref{-applify}) first to turn it into a unary function. With n = 0, this acts as identity function. In types: (a -> a) -> Int -> a -> a. This function satisfies the following law: (funcall (-iteratefn fn n) init) = (-last-item (-iterate fn init (1+ n))). @example @group (funcall (-iteratefn (lambda (x) (* x x)) 3) 2) @result{} 256 @end group @group (funcall (-iteratefn '1+ 3) 1) @result{} 4 @end group @group (funcall (-iteratefn 'cdr 3) '(1 2 3 4 5)) @result{} '(4 5) @end group @end example @end defun @anchor{-fixfn} @defun -fixfn (fn &optional equal-test halt-test) Return a function that computes the (least) fixpoint of @var{fn}. @var{fn} must be a unary function. The returned lambda takes a single argument, @var{x}, the initial value for the fixpoint iteration. The iteration halts when either of the following conditions is satisfied: 1. Iteration converges to the fixpoint, with equality being tested using @var{equal-test}. If @var{equal-test} is not specified, @code{equal} is used. For functions over the floating point numbers, it may be necessary to provide an appropriate approximate comparison test. 2. @var{halt-test} returns a non-nil value. @var{halt-test} defaults to a simple counter that returns t after @code{-fixfn-max-iterations}, to guard against infinite iteration. Otherwise, @var{halt-test} must be a function that accepts a single argument, the current value of @var{x}, and returns non-nil as long as iteration should continue. In this way, a more sophisticated convergence test may be supplied by the caller. The return value of the lambda is either the fixpoint or, if iteration halted before converging, a cons with car @code{halted} and cdr the final output from @var{halt-test}. In types: (a -> a) -> a -> a. @example @group (funcall (-fixfn 'cos 'approx-equal) 0.7) @result{} 0.7390851332151607 @end group @group (funcall (-fixfn (lambda (x) (expt (+ x 10) 0.25))) 2.0) @result{} 1.8555845286409378 @end group @group (funcall (-fixfn 'sin 'approx-equal) 0.1) @result{} '(halted . t) @end group @end example @end defun @anchor{-prodfn} @defun -prodfn (&rest fns) Take a list of n functions and return a function that takes a list of length n, applying i-th function to i-th element of the input list. Returns a list of length n. In types (for n=2): ((a -> b), (c -> d)) -> (a, c) -> (b, d) This function satisfies the following laws: (-compose (-prodfn f g @dots{}) (-prodfn f' g' @dots{})) = (-prodfn (-compose f f') (-compose g g') @dots{}) (-prodfn f g @dots{}) = (-juxt (-compose f (-partial 'nth 0)) (-compose g (-partial 'nth 1)) @dots{}) (-compose (-prodfn f g @dots{}) (-juxt f' g' @dots{})) = (-juxt (-compose f f') (-compose g g') @dots{}) (-compose (-partial 'nth n) (-prod f1 f2 @dots{})) = (-compose fn (-partial 'nth n)) @example @group (funcall (-prodfn '1+ '1- 'number-to-string) '(1 2 3)) @result{} '(2 1 "3") @end group @group (-map (-prodfn '1+ '1-) '((1 2) (3 4) (5 6) (7 8))) @result{} '((2 1) (4 3) (6 5) (8 7)) @end group @group (apply '+ (funcall (-prodfn 'length 'string-to-number) '((1 2 3) "15"))) @result{} 18 @end group @end example @end defun @node Development @chapter Development The Dash repository is hosted on GitHub at @url{https://github.com/magnars/dash.el}. @menu * Contribute:: How to contribute. * Change log:: List of significant changes by version. * Contributors:: List of contributors. @end menu @node Contribute @section Contribute Yes, please do. Pure functions in the list manipulation realm only, please. There's a suite of examples/tests in @file{dev/examples.el}, so remember to add tests for your additions, or they may get broken later. Run the tests with @samp{make check}. Regenerate the docs with @samp{make docs}. Contributors are encouraged to install these commands as a Git pre-commit hook, so that the tests are always running and the docs are always in sync: @example $ cp pre-commit.sh .git/hooks/pre-commit @end example Oh, and don't edit @file{README.md} or @file{dash.texi} directly, as they are auto-generated. Instead, change their respective templates @file{readme-template.md} or @file{dash-template.texi}. To ensure that Dash can be distributed with GNU ELPA or Emacs, we require that all contributors assign copyright to the Free Software Foundation. For more on this, @pxref{Copyright Assignment,,, emacs, The GNU Emacs Manual}. @node Change log @section Change log @table @asis @item Changes in 2.17: @itemize @item Sped up @code{-uniq} by using hash-tables when possible (Zhu Zihao). @item Fixed @code{-inits} to be non-destructive (Zach Shaftel). @item Fixed indent rules for @code{-some->} and family (Wouter Bolsterlee). @item Added @code{-zip-lists} which always returns a list of proper lists, even for two input lists (see issue #135). @end itemize @item Changes in 2.16: @itemize @item Added @code{--doto}, anaphoric version of @code{-doto}. @item Aliased @code{-cons-pair-p} to @code{-cons-pair?}. @item Generalized @code{-rotate} for @math{|@var{n}|} greater than the length of the list (Brian Leung). @item Added a mechanism to extend destructuring with custom matchers (Ivan Yonchovski). @end itemize @item Changes in 2.15: This release brought new destructuring features, some new control flow functions, and performance optimizations. @itemize @item Added @code{-setq} with destructuring binding support similar to the @code{-let} family. @item Added smarter key destructuring in @code{-let} and friends where variables are auto-derived from keys. @item Allowed @code{-let} bindings without a source value form. @item Added @code{-each-r} and @code{-each-r-while} (Paul Pogonyshev). @item Added @code{-common-suffix} (Basil L. Contovounesios). @item Improved performance of folds (@code{-reduce} and friends) (Basil L. Contovounesios). @end itemize @item Changes in 2.14: This release retired support for Emacs 23. @itemize @item Added Edebug support for threading macros (Wilfred Hughes). @item Added @code{-unzip}. @item Added support for @code{-first-item} and @code{-last-item} as place forms (@pxref{Generalized Variables,,, elisp, The Emacs Lisp Reference Manual}). @item Added @code{-powerset} and @code{-permutations} (Mark Oteiza). @item Added @code{-as->} for threading a named variable (Zachary Kanfer). @item Added @code{-partition-after-pred}, @code{-partition-before-pred}, @code{-partition-after-item}, and @code{-partition-before-item} (Zachary Kanfer). @item Fixed a bug in @code{-any-p} and friends testing for @code{null} on lists containing @code{nil}. @item Fixed infinite loop bug in @code{-zip} and @code{-interleave} when called with empty input. @item Added @code{-second-item} through @code{-fifth-item} as alternatives to @code{nth} (Wilfred Hughes). @item Added @code{-tails} and @code{-inits}. @item Added @code{-running-sum} and @code{-running-product}. @item Added the @code{-reductions[-r][-from]} family of functions (like @code{-reduce} but collecting intermediate results). @item Added @code{-common-prefix} (Basil L. Contovounesios). @end itemize @item Changes in 2.13: @itemize @item @code{-let} now supports @code{&alist} destructuring. @item Various performance improvements. @item @code{-zip} might change in a future release to always return a list of proper lists. Added @code{-zip-pair} for users who explicitly want the old behavior. @item Enabled lexical binding in @file{dash.el} for Emacs versions 24 or newer. @item Added @code{-select-column} and @code{-select-columns}. @item Fixed @code{-map-last} and @code{--remove-last} to be non-destructive. @item Added @code{-each-indexed} and @code{--each-indexed}. @item Added @code{-take-last} and @code{-drop-last}. @item Added the @code{-doto} macro. @item @code{-cut <>} is now treated as a function, consistent with @url{https://srfi.schemers.org/srfi-26/srfi-26.html, SRFI 26}. @end itemize @item Changes in 2.12: @itemize @item Added GNU ELPA support (Phillip Lord). @item Added @code{-some->}, @code{-some->>}, and @code{-some-->} macros (Cam Saul). @item @code{-is-suffix?} is now non-destructive. @item Faster hash table implementation for @code{-union}. @item Improvements to docstrings and examples. @end itemize @item Changes in 2.11: @itemize @item Lots of clean up w.r.t. byte compilation, debug macros, and tests. @end itemize @item Changes in 2.10: @itemize @item Added @code{-let} destructuring to @code{-if-let} and @code{-when-let} (Fredrik Bergroth). @end itemize @item Changes in 2.9: @itemize @item Added @code{-let}, @code{-let*}, and @code{-lambda} with destructuring. @item Added @code{-tree-seq} and @code{-tree-map-nodes}. @item Added @code{-non-nil}. @item Added @code{-fix}. @item Added @code{-fixfn} (@samp{dash-functional} version 1.2). @item Added @code{-copy} (Wilfred Hughes). @end itemize @item Changes in 2.8: @itemize @item Added @code{-butlast}. @end itemize @item Changes in 2.7: @itemize @item @code{-zip} now supports more than two lists (Steve Lamb). @item Added @code{-cycle}, @code{-pad}, @code{-annotate}, and @code{-zip-fill} (Steve Lamb). @item Added @code{-table}, @code{-table-flat} (finite Cartesian product). @item Added @code{-flatten-n}. @item @code{-slice} now supports a ``step'' argument. @item Added functional combinators @code{-iteratefn} and @code{-prodfn}. @item Added @code{-replace}, @code{-splice}, and @code{-splice-list} which generalize @code{-replace-at} and @code{-insert-at}. @item Added @code{-compose}, @code{-iteratefn}, and @code{-prodfn} (@samp{dash-functional} version 1.1). @end itemize @item Changes in 2.6: @itemize @item Added @code{-is-prefix-p}, @code{-is-suffix-p}, and @code{-is-infix-p} (Matus Goljer). @item Added @code{-iterate} and @code{-unfold} (Matus Goljer). @item Added @code{-split-on} and @code{-split-when} (Matus Goljer). @item Added @code{-find-last-index} (Matus Goljer). @item Added @code{-list} (Johan Andersson). @end itemize @item Changes in 2.5: @itemize @item Added @code{-same-items?} (Johan Andersson). @item Various bugfixes. @end itemize @item Changes in 2.4: @itemize @item Added @code{-snoc} (Matus Goljer). @item Added @code{-replace-at}, @code{-update-at}, @code{-remove-at}, and @code{-remove-at-indices} (Matus Goljer). @end itemize @item Changes in 2.3: @itemize @item Added tree operations (Matus Goljer). @item Made Font Lock optional. @end itemize @item Changes in 2.2: @itemize @item Added @code{-compose} (Christina Whyte). @end itemize @item Changes in 2.1: @itemize @item Added indexing operations (Matus Goljer). @end itemize @item Changes in 2.0: @itemize @item Split out @file{dash-functional.el} (Matus Goljer). @item Added @code{-andfn}, @code{-orfn}, @code{-not}, @code{-cut}, @code{-const}, @code{-flip}, and @code{-on} (Matus Goljer). @item Fixed @code{-min}, @code{-max}, @code{-min-by}, and @code{-max-by} (Matus Goljer). @end itemize @item Changes in 1.8: @itemize @item Added @code{-first-item} and @code{-last-item} (Wilfred Hughes). @end itemize @item Changes in 1.7: @itemize @item Added @code{-rotate} (Matus Goljer). @end itemize @item Changes in 1.6: @itemize @item Added @code{-min}, @code{-max}, @code{-min-by}, and @code{-max-by} (Johan Andersson). @end itemize @item Changes in 1.5: @itemize @item Added @code{-sum} and @code{-product} (Johan Andersson). @end itemize @item Changes in 1.4: @itemize @item Added @code{-sort}. @item Added @code{-reduce-r} (Matus Goljer). @item Added @code{-reduce-r-from} (Matus Goljer). @end itemize @item Changes in 1.3: @itemize @item Added @code{-partition-in-steps}. @item Added @code{-partition-all-in-steps}. @end itemize @item Changes in 1.2: @itemize @item Added @code{-last} (Matus Goljer). @item Added @code{-insert-at} (Emanuel Evans). @item Added @code{-when-let} and @code{-if-let} (Emanuel Evans). @item Added @code{-when-let*} and @code{-if-let*} (Emanuel Evans). @item Various bugfixes. @end itemize @end table @node Contributors @section Contributors @itemize @item @url{https://github.com/Fuco1, Matus Goljer} contributed lots of features and functions. @item @url{https://github.com/tkf, Takafumi Arakaki} contributed @code{-group-by}. @item @url{https://github.com/tali713, tali713} is the author of @code{-applify}. @item @url{https://github.com/vemv, V@'{i}ctor M. Valenzuela} contributed @code{-repeat}. @item @url{https://github.com/nicferrier, Nic Ferrier} contributed @code{-cons*}. @item @url{https://github.com/Wilfred, Wilfred Hughes} contributed @code{-slice}, @code{-first-item}, and @code{-last-item}. @item @url{https://github.com/shosti, Emanuel Evans} contributed @code{-if-let}, @code{-when-let}, and @code{-insert-at}. @item @url{https://github.com/rejeep, Johan Andersson} contributed @code{-sum}, @code{-product}, and @code{-same-items?}. @item @url{https://github.com/kurisuwhyte, Christina Whyte} contributed @code{-compose}. @item @url{https://github.com/steventlamb, Steve Lamb} contributed @code{-cycle}, @code{-pad}, @code{-annotate}, @code{-zip-fill}, and a variadic version of @code{-zip}. @item @url{https://github.com/fbergroth, Fredrik Bergroth} made the @code{-if-let} family use @code{-let} destructuring and improved the script for generating documentation. @item @url{https://github.com/holomorph, Mark Oteiza} contributed the script to create an Info manual. @item @url{https://github.com/wasamasa, Vasilij Schneidermann} contributed @code{-some}. @item @url{https://github.com/occidens, William West} made @code{-fixfn} more robust at handling floats. @item @url{https://github.com/camsaul, Cam Saul} contributed @code{-some->}, @code{-some->>}, and @code{-some-->}. @item @url{https://github.com/basil-conto, Basil L. Contovounesios} contributed @code{-common-prefix}. @item @url{https://github.com/doublep, Paul Pogonyshev} contributed @code{-each-r} and @code{-each-r-while}. @end itemize Thanks! New contributors are very welcome. @xref{Contribute}. @c Appendices. @node FDL @appendix GNU Free Documentation License @include doc/fdl.texi @node GPL @appendix GNU General Public License @include doc/gpl.texi @node Index @unnumbered Index @printindex fn @bye