\input texinfo @c -*- texinfo -*- @c %**start of header @setfilename dash.info @settitle dash @documentencoding UTF-8 @documentlanguage en @syncodeindex fn cp @dircategory Emacs @direntry * Dash: (dash.info). A modern list library for GNU Emacs @end direntry @c %**end of header @copying This manual is for @code{dash.el} version 2.12.1. Copyright © 2012-2015 Magnar Sveen @quotation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see @uref{http://www.gnu.org/licenses/}. @end quotation @end copying @finalout @titlepage @title Dash @author Magnar Sveen @page @vskip 0pt plus 1filll @insertcopying @end titlepage @contents @ifnottex @node Top @top dash @insertcopying @end ifnottex @menu * Installation:: * Functions:: * Development:: * Index:: @detailmenu --- The Detailed Node Listing --- Installation * Using in a package:: * Syntax highlighting of dash functions:: 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 * Changes:: List of significant changes by version * Contributors:: List of contributors @end detailmenu @end menu @node Installation @chapter Installation It's available on @uref{http://marmalade-repo.org/,marmalade} and @uref{https://melpa.org/,Melpa}; use @code{M-x package-install}: @table @kbd @item M-x package-install @key{RET} dash Install the dash library. @end table @table @kbd @item M-x package-install @key{RET} dash-functional Optional, if you want the function combinators. @end table Alternatively, you can just dump @verb{~dash.el~} or @verb{~dash-functional.el~} in your load path somewhere. @menu * Using in a package:: * Syntax highlighting of dash functions:: @end menu @node Using in a package @section Using in a package Add this to the big comment block at the top: @lisp ;; Package-Requires: ((dash "2.12.1")) @end lisp @noindent To get function combinators: @lisp ;; Package-Requires: ((dash "2.12.1") (dash-functional "1.2.0") (emacs "24")) @end lisp @node Syntax highlighting of dash functions @section Syntax highlighting of dash functions Font lock of dash functions in emacs lisp buffers is now optional. Include this in your emacs settings to get syntax highlighting: @lisp (eval-after-load 'dash '(dash-enable-font-lock)) @end lisp @node Functions @chapter Functions This chapter contains reference documentation for the dash @abbr{application programming interface,API}. All functions and constructs in the library are prefixed with a dash (-). There are also anaphoric versions of functions where that makes sense, prefixed with two dashes instead of one. For instance, while @code{-map} takes a function to map over the list, one can also use the anaphoric form with double dashes - which will then be executed with @code{it} exposed as the list item. Here's an example: @lisp (-map (lambda (n) (* n n)) '(1 2 3 4)) ;; normal version (--map (* it it) '(1 2 3 4)) ;; anaphoric version @end lisp @noindent Of course, the original can also be written like @lisp (defun square (n) (* n n)) (-map 'square '(1 2 3 4)) @end lisp @noindent which demonstrates the usefulness of both versions. @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 occurences 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 new list of the first @var{n} items in @var{list}, or all items if there are fewer than @var{n}. 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 @end example @end defun @anchor{-take-last} @defun -take-last (n list) Return the last @var{n} items of @var{list} in order. 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 the tail of @var{list} without the first @var{n} items. See also: @code{-drop-last} (@pxref{-drop-last}) (fn @var{n} @var{list}) @example @group (-drop 3 '(1 2 3 4 5)) @result{} '(4 5) @end group @group (-drop 17 '(1 2 3 4 5)) @result{} '() @end group @end example @end defun @anchor{-drop-last} @defun -drop-last (n list) Remove the last @var{n} items of @var{list} and return a copy. 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{} '() @end group @end example @end defun @anchor{-take-while} @defun -take-while (pred list) Return a new list of successive items from @var{list} while (@var{pred} item) returns a non-nil value. @example @group (-take-while 'even? '(1 2 3 4)) @result{} '() @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) Return the tail of @var{list} starting from the first item for which (@var{pred} item) returns nil. @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 occurence 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 occurence 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) nil '(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{-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 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 form: (init (fun init) (fun (fun init)) ...) @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 #'oddp '()) @result{} '() @end group @group (-partition-after-pred #'oddp '(1)) @result{} '((1)) @end group @group (-partition-after-pred #'oddp '(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 #'oddp '()) @result{} '() @end group @group (-partition-before-pred #'oddp '(1)) @result{} '((1)) @end group @group (-partition-before-pred #'oddp '(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 @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 @end example @end defun @anchor{-repeat} @defun -repeat (n x) Return a list with @var{x} repeated @var{n} times. 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. Please note! This distinction is being removed in an upcoming 3.0 release of Dash. If you rely on this behavior, use -zip-pair instead. @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) '(4 5 6)) @result{} '((1 . 4) (2 . 5) (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} ...)) is identity (given that the lists are the same length). 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 @end example @end defun @anchor{-cycle} @defun -cycle (list) Return an infinite copy of @var{list} that will cycle through the elements and repeat 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 in 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})) ..) becomes (-let [@var{pattern} @var{source}] ..). @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 ...) - bind 0th car of list to @var{a1}, 1st to @var{a2}, 2nd to @var{a3} ... (a1 a2 a3 ... 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...) [a1 a2 a3 ...] - bind 0th element of non-list sequence to @var{a0}, 1st to @var{a1}, 2nd to @var{a2}, ... 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 ... &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 ... aN . rest) Key/value stores: (&plist key0 a0 ... 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 ... 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 ... 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 ... aN &keys key1 b1 ... keyN bK) This binds @var{n} values from the list to a1 ... 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 ...) 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}]...) @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) (!cons item s))) s) @result{} '(4 2) @end group @group (let (s) (--each-while '(1 2 3 4) (< it 3) (!cons it s)) s) @result{} '(2 1) @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) Repeatedly calls @var{fn} (presumably for side-effects) passing in integers from 0 through @var{num-1}. @example @group (let (s) (-dotimes 3 (lambda (n) (!cons n s))) s) @result{} '(2 1 0) @end group @group (let (s) (--dotimes 5 (!cons 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 @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) 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 @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 satisified: 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 appoximate comparsion 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 ...) (-prodfn f' g' ...)) = (-prodfn (-compose f f') (-compose g g') ...) (-prodfn f g ...) = (-juxt (-compose f (-partial 'nth 0)) (-compose g (-partial 'nth 1)) ...) (-compose (-prodfn f g ...) (-juxt f' g' ...)) = (-juxt (-compose f f') (-compose g g') ...) (-compose (-partial 'nth n) (-prod f1 f2 ...)) = (-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: @uref{https://github.com/magnars/dash.el} @menu * Contribute:: How to contribute * Changes:: 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 tests in @verb{~dev/examples.el~}, so remember to add tests for your function, or it might get broken later. Run the tests with @code{./run-tests.sh}. Create the docs with @code{./create-docs.sh}. I highly recommend that you install these as a pre-commit hook, so that the tests are always running and the docs are always in sync: @verbatim cp pre-commit.sh .git/hooks/pre-commit @end verbatim Oh, and don't edit @file{README.md} directly, it is auto-generated. Change @file{readme-template.md} or @file{examples-to-docs.el} instead. The same goes for the info manual. @node Changes @section Changes @noindent Changes in 2.10: @itemize @item Add @code{-let} destructuring to @code{-if-let} and @code{-when-let} (Fredrik Bergroth) @end itemize @noindent Changes in 2.9: @itemize @item Add @code{-let}, @code{-let*} and @code{-lambda} with destructuring @item Add @code{-tree-seq} and @code{-tree-map-nodes} @item Add @code{-non-nil} @item Add @code{-fix} @item Add @code{-fixfn} (dash-functional 1.2) @item Add @code{-copy} (Wilfred Hughes) @end itemize @noindent Changes in 2.8: @itemize @item Add @code{-butlast} @end itemize @noindent Changes in 2.7: @itemize @item @code{-zip} now supports more than two lists (Steve Lamb) @item Add @code{-cycle}, @code{-pad}, @code{-annotate}, @code{-zip-fill} (Steve Lamb) @item Add @code{-table}, @code{-table-flat} (finite cartesian product) @item Add @code{-flatten-n} @item @code{-slice} now supports "step" argument @item Add functional combinators @code{-iteratefn}, @code{-prodfn} @item Add @code{-replace}, @code{-splice}, @code{-splice-list} which generalize @code{-replace-at} and @code{-insert-at} @item Add @code{-compose}, @code{-iteratefn} and @code{-prodfn} (dash-functional 1.1) @end itemize @noindent Changes in 2.6: @itemize @item Add @code{-is-prefix-p}, @code{-is-suffix-p}, @code{-is-infix-p} (Matus Goljer) @item Add @code{-iterate}, @code{-unfold} (Matus Goljer) @item Add @code{-split-on}, @code{-split-when} (Matus Goljer) @item Add @code{-find-last-index} (Matus Goljer) @item Add @code{-list} (Johan Andersson) @end itemize @noindent Changes in 2.5: @itemize @item Add @code{-same-items?} (Johan Andersson) @item A few bugfixes @end itemize @noindent Changes in 2.4: @itemize @item Add @code{-snoc} (Matus Goljer) @item Add @code{-replace-at}, @code{-update-at}, @code{-remove-at}, and @code{-remove-at-indices} (Matus Goljer) @end itemize @noindent Changes in 2.3: @itemize @item Add tree operations (Matus Goljer) @item Make font-lock optional @end itemize @noindent Changes in 2.2: @itemize @item Add @code{-compose} (Christina Whyte) @end itemize @noindent Changes in 2.1: @itemize @item Add indexing operations (Matus Goljer) @end itemize @noindent Changes in 2.0: @itemize @item Split out @code{dash-functional.el} (Matus Goljer) @item Add @code{-andfn}, @code{-orfn}, @code{-not}, @code{-cut}, @code{-const}, @code{-flip} and @code{-on}. (Matus Goljer) @item Fix @code{-min}, @code{-max}, @code{-min-by} and @code{-max-by} (Matus Goljer) @end itemize @noindent Changes in 1.8: @itemize @item Add @code{-first-item} and @code{-last-item} (Wilfred Hughes) @end itemize @noindent Changes in 1.7: @itemize @item Add @code{-rotate} (Matus Goljer) @end itemize @noindent Changes in 1.6: @itemize @item Add @code{-min}, @code{-max}, @code{-min-by} and @code{-max-by} (Johan Andersson) @end itemize @noindent Changes in 1.5: @itemize @item Add @code{-sum} and @code{-product} (Johan Andersson) @end itemize @noindent Changes in 1.4: @itemize @item Add @code{-sort} @item Add @code{-reduce-r} (Matus Goljer) @item Add @code{-reduce-r-from} (Matus Goljer) @end itemize @noindent Changes in 1.3: @itemize @item Add @code{-partition-in-steps} @item Add @code{-partition-all-in-steps} @end itemize @noindent Changes in 1.2: @itemize @item Add @code{-last} (Matus Goljer) @item Add @code{-insert-at} (Emanuel Evans) @item Add @code{-when-let} and @code{-if-let} (Emanuel Evans) @item Add @code{-when-let*} and @code{-if-let*} (Emanuel Evans) @item Some bugfixes @end itemize @node Contributors @section Contributors @itemize @item @uref{https://github.com/Fuco1,Matus Goljer} contributed lots of features and functions. @item @uref{https://github.com/tkf,Takafumi Arakaki} contributed @code{-group-by}. @item @uref{https://github.com/tali713,tali713} is the author of @code{-applify}. @item @uref{https://github.com/vemv,Víctor M. Valenzuela} contributed @code{-repeat}. @item @uref{https://github.com/nicferrier,Nic Ferrier} contributed @code{-cons*}. @item @uref{https://github.com/Wilfred,Wilfred Hughes} contributed @code{-slice}, @code{-first-item} and @code{-last-item}. @item @uref{https://github.com/shosti,Emanuel Evans} contributed @code{-if-let}, @code{-when-let} and @code{-insert-at}. @item @uref{https://github.com/rejeep,Johan Andersson} contributed @code{-sum}, @code{-product} and @code{-same-items?} @item @uref{https://github.com/kurisuwhyte,Christina Whyte} contributed @code{-compose} @item @uref{https://github.com/steventlamb,Steve Lamb} contributed @code{-cycle}, @code{-pad}, @code{-annotate}, @code{-zip-fill} and an n-ary version of @code{-zip}. @item @uref{https://github.com/fbergroth,Fredrik Bergroth} made the @code{-if-let} family use @code{-let} destructuring and improved script for generating documentation. @item @uref{https://github.com/holomorph,Mark Oteiza} contributed the script to create an info manual. @item @uref{https://github.com/wasamasa,Vasilij Schneidermann} contributed @code{-some}. @item @uref{https://github.com/occidens,William West} made @code{-fixfn} more robust at handling floats. @end itemize Thanks! @node Index @unnumbered Index @printindex cp @bye