\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 "" sn ">")))) '(body (p "some words") (div "more" (b "bold") "words"))) @result{} "some words