A modern list api for Emacs. No 'cl required.
-
The
-min
and-max
functions are no longer variadic, but take a list to be more in line with the other dash functions. -
-min-by
and-max-by
now take a comparator function to sort by.
The stated scope of dash is increasing. It now includes more functional style functions, like combinators and threading macros. These have been creeping in anyway, since they're so darn useful. Time to make it official. :)
-rpartial
,-juxt
and-applify
are moved to a separate package. Note that-partial
is still in dash for backwards compatibility reasons.
These new combinators require Emacs 24 for its lexical scope. So
they are offered in a separate package: dash-functional
.
It's available on marmalade and Melpa:
M-x package-install dash
Or you can just dump dash.el
in your load
path somewhere.
If you want the function combinators, then also:
M-x package-install dash-functional
Add this to the big comment block at the top:
;; Package-Requires: ((dash "1.8.0"))
To get function combinators:
;; Package-Requires: ((dash "1.8.0") (dash-functional "1.0.0") (emacs "24"))
- -map
(fn list)
- -filter
(pred list)
- -remove
(pred list)
- -keep
(fn list)
- -map-when
(pred rep list)
- -map-indexed
(fn list)
- -flatten
(l)
- -concat
(&rest lists)
- -mapcat
(fn list)
- -slice
(list from &optional to)
- -take
(n list)
- -drop
(n list)
- -take-while
(pred list)
- -drop-while
(pred list)
- -rotate
(n list)
- -insert-at
(n x list)
- -reduce-from
(fn initial-value list)
- -reduce-r-from
(fn initial-value list)
- -reduce
(fn list)
- -reduce-r
(fn list)
- -count
(pred list)
- -sum
(list)
- -product
(list)
- -min
(list)
- -min-by
(comparator list)
- -max
(list)
- -max-by
(comparator list)
- -any?
(pred list)
- -all?
(pred list)
- -none?
(pred list)
- -only-some?
(pred list)
- -contains?
(list element)
- -split-at
(n list)
- -split-with
(pred list)
- -separate
(pred list)
- -partition
(n list)
- -partition-all-in-steps
(n step list)
- -partition-in-steps
(n step list)
- -partition-all
(n list)
- -partition-by
(fn list)
- -partition-by-header
(fn list)
- -group-by
(fn list)
- -elem-index
(elem list)
- -elem-indices
(elem list)
- -find-index
(pred list)
- -find-indices
(pred list)
- -select-by-indices
(indices list)
- -grade-up
(comparator list)
- -grade-down
(comparator list)
- -union
(list list2)
- -difference
(list list2)
- -intersection
(list list2)
- -distinct
(list)
- -repeat
(n x)
- -cons*
(&rest args)
- -interpose
(sep list)
- -interleave
(&rest lists)
- -zip-with
(fn list1 list2)
- -zip
(list1 list2)
- -first
(pred list)
- -last
(pred list)
- -first-item
(list)
- -last-item
(list)
- -sort
(comparator list)
- -when-let
(var-val &rest body)
- -when-let*
(vars-vals &rest body)
- -if-let
(var-val then &optional else)
- -if-let*
(vars-vals then &optional else)
- -each
(list fn)
- -each-while
(list pred fn)
- -dotimes
(num fn)
These combinators require Emacs 24 for its lexical scope. So they are offered in a separate package: dash-functional
.
- -partial
(fn &rest args)
- -rpartial
(fn &rest args)
- -juxt
(&rest fns)
- -applify
(fn)
- -on
(operator transformer)
- -flip
(func)
- -const
(c)
- -cut
(&rest params)
- -not
(pred)
- -orfn
(&rest preds)
- -andfn
(&rest preds)
There are also anaphoric versions of functions where that makes sense, prefixed with two dashes instead of one.
While -map
takes a function to map over the list, you can also use
the anaphoric form with double dashes - which will then be executed
with it
exposed as the list item. Here's an example:
(-map (lambda (n) (* n n)) '(1 2 3 4)) ;; normal version
(--map (* it it) '(1 2 3 4)) ;; anaphoric version
of course the original can also be written like
(defun square (n) (* n n))
(-map 'square '(1 2 3 4))
which demonstrates the usefulness of both versions.
Returns a new list consisting of the result of applying fn
to the items in list
.
(-map (lambda (num) (* num num)) '(1 2 3 4)) ;; => '(1 4 9 16)
(-map 'square '(1 2 3 4)) ;; => '(1 4 9 16)
(--map (* it it) '(1 2 3 4)) ;; => '(1 4 9 16)
Returns a new list of the items in list
for which pred
returns a non-nil value.
Alias: -select
(-filter (lambda (num) (= 0 (% num 2))) '(1 2 3 4)) ;; => '(2 4)
(-filter 'even? '(1 2 3 4)) ;; => '(2 4)
(--filter (= 0 (% it 2)) '(1 2 3 4)) ;; => '(2 4)
Returns a new list of the items in list
for which pred
returns nil.
Alias: -reject
(-remove (lambda (num) (= 0 (% num 2))) '(1 2 3 4)) ;; => '(1 3)
(-remove 'even? '(1 2 3 4)) ;; => '(1 3)
(--remove (= 0 (% it 2)) '(1 2 3 4)) ;; => '(1 3)
Returns a new list of the non-nil results of applying fn
to the items in list
.
(-keep 'cdr '((1 2 3) (4 5) (6))) ;; => '((2 3) (5))
(-keep (lambda (num) (when (> num 3) (* 10 num))) '(1 2 3 4 5 6)) ;; => '(40 50 60)
(--keep (when (> it 3) (* 10 it)) '(1 2 3 4 5 6)) ;; => '(40 50 60)
Returns a new list where the elements in list
that does not match the pred
function
are unchanged, and where the elements in list
that do match the pred
function are mapped
through the rep
function.
(-map-when 'even? 'square '(1 2 3 4)) ;; => '(1 4 3 16)
(--map-when (> it 2) (* it it) '(1 2 3 4)) ;; => '(1 2 9 16)
(--map-when (= it 2) 17 '(1 2 3 4)) ;; => '(1 17 3 4)
Returns a new list consisting of the result of (fn
index item) for each item in list
.
In the anaphoric form --map-indexed
, the index is exposed as it-index
.
(-map-indexed (lambda (index item) (- item index)) '(1 2 3 4)) ;; => '(1 1 1 1)
(--map-indexed (- it it-index) '(1 2 3 4)) ;; => '(1 1 1 1)
Takes a nested list l
and returns its contents as a single, flat list.
(-flatten '((1))) ;; => '(1)
(-flatten '((1 (2 3) (((4 (5))))))) ;; => '(1 2 3 4 5)
(-flatten '(1 2 (3 . 4))) ;; => '(1 2 (3 . 4))
Returns a new list with the concatenation of the elements in the supplied lists
.
(-concat '(1)) ;; => '(1)
(-concat '(1) '(2)) ;; => '(1 2)
(-concat '(1) '(2 3) '(4)) ;; => '(1 2 3 4)
Returns the concatenation of the result of mapping fn
over list
.
Thus function fn
should return a list.
(-mapcat 'list '(1 2 3)) ;; => '(1 2 3)
(-mapcat (lambda (item) (list 0 item)) '(1 2 3)) ;; => '(0 1 0 2 0 3)
(--mapcat (list 0 it) '(1 2 3)) ;; => '(0 1 0 2 0 3)
Return copy of list
, starting from index from
to index to
.
from
or to
may be negative.
(-slice '(1 2 3 4 5) 1) ;; => '(2 3 4 5)
(-slice '(1 2 3 4 5) 0 3) ;; => '(1 2 3)
(-slice '(1 2 3 4 5) 1 -1) ;; => '(2 3 4)
Returns a new list of the first n
items in list
, or all items if there are fewer than n
.
(-take 3 '(1 2 3 4 5)) ;; => '(1 2 3)
(-take 17 '(1 2 3 4 5)) ;; => '(1 2 3 4 5)
Returns the tail of list
without the first n
items.
(-drop 3 '(1 2 3 4 5)) ;; => '(4 5)
(-drop 17 '(1 2 3 4 5)) ;; => '()
Returns a new list of successive items from list
while (pred
item) returns a non-nil value.
(-take-while 'even? '(1 2 3 4)) ;; => '()
(-take-while 'even? '(2 4 5 6)) ;; => '(2 4)
(--take-while (< it 4) '(1 2 3 4 3 2 1)) ;; => '(1 2 3)
Returns the tail of list
starting from the first item for which (pred
item) returns nil.
(-drop-while 'even? '(1 2 3 4)) ;; => '(1 2 3 4)
(-drop-while 'even? '(2 4 5 6)) ;; => '(5 6)
(--drop-while (< it 4) '(1 2 3 4 3 2 1)) ;; => '(4 3 2 1)
Rotate list
n
places to the right. With n
negative, rotate to the left.
The time complexity is o
(n).
(-rotate 3 '(1 2 3 4 5 6 7)) ;; => '(5 6 7 1 2 3 4)
(-rotate -3 '(1 2 3 4 5 6 7)) ;; => '(4 5 6 7 1 2 3)
Returns a list with x
inserted into list
at position n
.
(-insert-at 1 'x '(a b c)) ;; => '(a x b c)
(-insert-at 12 'x '(a b c)) ;; => '(a b c x)
Returns the result of applying fn
to initial-value
and the
first item in list
, then applying fn
to that result and the 2nd
item, etc. If list
contains no items, returns initial-value
and
fn
is not called.
In the anaphoric form --reduce-from
, the accumulated value is
exposed as acc
.
(-reduce-from '- 10 '(1 2 3)) ;; => 4
(-reduce-from (lambda (memo item) (concat "(" memo " - " (int-to-string item) ")")) "10" '(1 2 3)) ;; => "(((10 - 1) - 2) - 3)"
(--reduce-from (concat acc " " it) "START" '("a" "b" "c")) ;; => "START a b c"
Replace conses with fn
, nil with initial-value
and evaluate
the resulting expression. If list
is empty, initial-value
is
returned and fn
is not called.
Note: this function works the same as -reduce-from
but the
operation associates from right instead of from left.
(-reduce-r-from '- 10 '(1 2 3)) ;; => -8
(-reduce-r-from (lambda (item memo) (concat "(" (int-to-string item) " - " memo ")")) "10" '(1 2 3)) ;; => "(1 - (2 - (3 - 10)))"
(--reduce-r-from (concat it " " acc) "END" '("a" "b" "c")) ;; => "a b c END"
Returns the result of applying fn
to the first 2 items in list
,
then applying fn
to that result and the 3rd item, etc. If list
contains no items, fn
must accept no arguments as well, and
reduce returns the result of calling fn
with no arguments. If
list
has only 1 item, it is returned and fn
is not called.
In the anaphoric form --reduce
, the accumulated value is
exposed as acc
.
(-reduce '- '(1 2 3 4)) ;; => -8
(-reduce (lambda (memo item) (format "%s-%s" memo item)) '(1 2 3)) ;; => "1-2-3"
(--reduce (format "%s-%s" acc it) '(1 2 3)) ;; => "1-2-3"
Replace conses with fn
and evaluate the resulting expression.
The final nil is ignored. If list
contains no items, fn
must
accept no arguments as well, and reduce returns the result of
calling fn
with no arguments. If list
has only 1 item, it is
returned and fn
is not called.
The first argument of fn
is the new item, the second is the
accumulated value.
Note: this function works the same as -reduce
but the operation
associates from right instead of from left.
(-reduce-r '- '(1 2 3 4)) ;; => -2
(-reduce-r (lambda (item memo) (format "%s-%s" memo item)) '(1 2 3)) ;; => "3-2-1"
(--reduce-r (format "%s-%s" acc it) '(1 2 3)) ;; => "3-2-1"
Counts the number of items in list
where (pred
item) is non-nil.
(-count 'even? '(1 2 3 4 5)) ;; => 2
(--count (< it 4) '(1 2 3 4)) ;; => 3
Return the sum of list
.
(-sum '()) ;; => 0
(-sum '(1)) ;; => 1
(-sum '(1 2 3)) ;; => 6
Return the product of list
.
(-product '()) ;; => 1
(-product '(1)) ;; => 1
(-product '(1 2 3)) ;; => 6
Return the smallest value from list
of numbers or markers.
(-min '(0)) ;; => 0
(-min '(3 2 1)) ;; => 1
(-min '(1 2 3)) ;; => 1
Take a comparison function comparator
and a list
and return
the least element of the list by the comparison function.
See also combinator -on
which can transform the values before
comparing them.
(-min-by '> '(4 3 6 1)) ;; => 1
(-min-by '< '(4 3 6 1)) ;; => 6
(--min-by (> (length it) (length other)) '((1 2 3) (1) (1 2))) ;; => '(1)
Return the largest value from list
of numbers or markers.
(-max '(0)) ;; => 0
(-max '(3 2 1)) ;; => 3
(-max '(1 2 3)) ;; => 3
Take a comparison function comparator
and a list
and return
the greatest element of the list by the comparison function.
See also combinator -on
which can transform the values before
comparing them.
(-max-by '> '(4 3 6 1)) ;; => 6
(--max-by (> (car it) (car other)) '((2 2 3) (3) (1 2))) ;; => '(3)
(-max-by '< '(4 3 6 1)) ;; => 1
Returns t if (pred
x) is non-nil for any x in list
, else nil.
Alias: -some?
(-any? 'even? '(1 2 3)) ;; => t
(-any? 'even? '(1 3 5)) ;; => nil
(--any? (= 0 (% it 2)) '(1 2 3)) ;; => t
Returns t if (pred
x) is non-nil for all x in list
, else nil.
Alias: -every?
(-all? 'even? '(1 2 3)) ;; => nil
(-all? 'even? '(2 4 6)) ;; => t
(--all? (= 0 (% it 2)) '(2 4 6)) ;; => t
Returns t if (pred
x) is nil for all x in list
, else nil.
(-none? 'even? '(1 2 3)) ;; => nil
(-none? 'even? '(1 3 5)) ;; => t
(--none? (= 0 (% it 2)) '(1 2 3)) ;; => nil
Returns t
if there is a mix of items in list
that matches and does not match pred
.
Returns nil
both if all items match the predicate, and if none of the items match the predicate.
(-only-some? 'even? '(1 2 3)) ;; => t
(-only-some? 'even? '(1 3 5)) ;; => nil
(-only-some? 'even? '(2 4 6)) ;; => nil
Return whether list
contains element
.
The test for equality is done with equal
,
or with -compare-fn
if that's non-nil.
(-contains? '(1 2 3) 1) ;; => t
(-contains? '(1 2 3) 2) ;; => t
(-contains? '(1 2 3) 4) ;; => nil
Returns a list of ((-take n
list
) (-drop n
list
)), in no more than one pass through the list.
(-split-at 3 '(1 2 3 4 5)) ;; => '((1 2 3) (4 5))
(-split-at 17 '(1 2 3 4 5)) ;; => '((1 2 3 4 5) nil)
Returns a list of ((-take-while pred
list
) (-drop-while pred
list
)), in no more than one pass through the list.
(-split-with 'even? '(1 2 3 4)) ;; => '(nil (1 2 3 4))
(-split-with 'even? '(2 4 5 6)) ;; => '((2 4) (5 6))
(--split-with (< it 4) '(1 2 3 4 3 2 1)) ;; => '((1 2 3) (4 3 2 1))
Returns a list of ((-filter pred
list
) (-remove pred
list
)), in one pass through the list.
(-separate (lambda (num) (= 0 (% num 2))) '(1 2 3 4 5 6 7)) ;; => '((2 4 6) (1 3 5 7))
(--separate (< it 5) '(3 7 5 9 3 2 1 4 6)) ;; => '((3 3 2 1 4) (7 5 9 6))
(-separate 'cdr '((1 2) (1) (1 2 3) (4))) ;; => '(((1 2) (1 2 3)) ((1) (4)))
Returns a new list with the items in list
grouped into n-
sized sublists.
If there are not enough items to make the last group n-
sized,
those items are discarded.
(-partition 2 '(1 2 3 4 5 6)) ;; => '((1 2) (3 4) (5 6))
(-partition 2 '(1 2 3 4 5 6 7)) ;; => '((1 2) (3 4) (5 6))
(-partition 3 '(1 2 3 4 5 6 7)) ;; => '((1 2 3) (4 5 6))
Returns a new list with the items in list
grouped into n-
sized sublists at offsets step
apart.
The last groups may contain less than n
items.
(-partition-all-in-steps 2 1 '(1 2 3 4)) ;; => '((1 2) (2 3) (3 4) (4))
(-partition-all-in-steps 3 2 '(1 2 3 4)) ;; => '((1 2 3) (3 4))
(-partition-all-in-steps 3 2 '(1 2 3 4 5)) ;; => '((1 2 3) (3 4 5) (5))
Returns a new list with the items in list
grouped into n-
sized sublists at offsets step
apart.
If there are not enough items to make the last group n-
sized,
those items are discarded.
(-partition-in-steps 2 1 '(1 2 3 4)) ;; => '((1 2) (2 3) (3 4))
(-partition-in-steps 3 2 '(1 2 3 4)) ;; => '((1 2 3))
(-partition-in-steps 3 2 '(1 2 3 4 5)) ;; => '((1 2 3) (3 4 5))
Returns a new list with the items in list
grouped into n-
sized sublists.
The last group may contain less than n
items.
(-partition-all 2 '(1 2 3 4 5 6)) ;; => '((1 2) (3 4) (5 6))
(-partition-all 2 '(1 2 3 4 5 6 7)) ;; => '((1 2) (3 4) (5 6) (7))
(-partition-all 3 '(1 2 3 4 5 6 7)) ;; => '((1 2 3) (4 5 6) (7))
Applies fn
to each item in list
, splitting it each time fn
returns a new value.
(-partition-by 'even? '()) ;; => '()
(-partition-by 'even? '(1 1 2 2 2 3 4 6 8)) ;; => '((1 1) (2 2 2) (3) (4 6 8))
(--partition-by (< it 3) '(1 2 3 4 3 2 1)) ;; => '((1 2) (3 4 3) (2 1))
Applies fn
to the first item in list
. That is the header
value. Applies fn
to each item in list
, splitting it each time
fn
returns the header value, but only after seeing at least one
other value (the body).
(--partition-by-header (= it 1) '(1 2 3 1 2 1 2 3 4)) ;; => '((1 2 3) (1 2) (1 2 3 4))
(--partition-by-header (> it 0) '(1 2 0 1 0 1 2 3 0)) ;; => '((1 2 0) (1 0) (1 2 3 0))
(-partition-by-header 'even? '(2 1 1 1 4 1 3 5 6 6 1)) ;; => '((2 1 1 1) (4 1 3 5) (6 6 1))
Separate list
into an alist whose keys are fn
applied to the
elements of list
. Keys are compared by equal
.
(-group-by 'even? '()) ;; => '()
(-group-by 'even? '(1 1 2 2 2 3 4 6 8)) ;; => '((nil 1 1 3) (t 2 2 2 4 6 8))
(--group-by (car (split-string it "/")) '("a/b" "c/d" "a/e")) ;; => '(("a" "a/b" "a/e") ("c" "c/d"))
Return the index of the first element in the given list
which
is equal to the query element elem
, or nil if there is no
such element.
(-elem-index 2 '(6 7 8 2 3 4)) ;; => 3
(-elem-index "bar" '("foo" "bar" "baz")) ;; => 1
(-elem-index '(1 2) '((3) (5 6) (1 2) nil)) ;; => 2
Return the indices of all elements in list
equal to the query
element elem
, in ascending order.
(-elem-indices 2 '(6 7 8 2 3 4 2 1)) ;; => '(3 6)
(-elem-indices "bar" '("foo" "bar" "baz")) ;; => '(1)
(-elem-indices '(1 2) '((3) (1 2) (5 6) (1 2) nil)) ;; => '(1 3)
Take a predicate pred
and a list
and return the index of the
first element in the list satisfying the predicate, or nil if
there is no such element.
(-find-index 'even? '(2 4 1 6 3 3 5 8)) ;; => 0
(--find-index (< 5 it) '(2 4 1 6 3 3 5 8)) ;; => 3
(-find-index (-partial 'string-lessp "baz") '("bar" "foo" "baz")) ;; => 1
Return the indices of all elements in list
satisfying the
predicate pred
, in ascending order.
(-find-indices 'even? '(2 4 1 6 3 3 5 8)) ;; => '(0 1 3 7)
(--find-indices (< 5 it) '(2 4 1 6 3 3 5 8)) ;; => '(3 7)
(-find-indices (-partial 'string-lessp "baz") '("bar" "foo" "baz")) ;; => '(1)
Return a list whose elements are elements from list
selected
as (nth i list)
for all i from indices
.
(-select-by-indices '(4 10 2 3 6) '("v" "e" "l" "o" "c" "i" "r" "a" "p" "t" "o" "r")) ;; => '("c" "o" "l" "o" "r")
(-select-by-indices '(2 1 0) '("a" "b" "c")) ;; => '("c" "b" "a")
(-select-by-indices '(0 1 2 0 1 3 3 1) '("f" "a" "r" "l")) ;; => '("f" "a" "r" "f" "a" "l" "l" "a")
Grades elements of list
using comparator
relation, yielding a
permutation vector such that applying this permutation to list
sorts it in ascending order.
(-grade-up '< '(3 1 4 2 1 3 3)) ;; => '(1 4 3 0 5 6 2)
(let ((l '(3 1 4 2 1 3 3))) (-select-by-indices (-grade-up '< l) l)) ;; => '(1 1 2 3 3 3 4)
Grades elements of list
using comparator
relation, yielding a
permutation vector such that applying this permutation to list
sorts it in descending order.
(-grade-down '< '(3 1 4 2 1 3 3)) ;; => '(2 0 5 6 3 1 4)
(let ((l '(3 1 4 2 1 3 3))) (-select-by-indices (-grade-down '< l) l)) ;; => '(4 3 3 3 2 1 1)
Return a new list containing the elements of list1
and elements of list2
that are not in list1
.
The test for equality is done with equal
,
or with -compare-fn
if that's non-nil.
(-union '(1 2 3) '(3 4 5)) ;; => '(1 2 3 4 5)
(-union '(1 2 3 4) '()) ;; => '(1 2 3 4)
(-union '(1 1 2 2) '(3 2 1)) ;; => '(1 1 2 2 3)
Return a new list with only the members of list
that are not in list2
.
The test for equality is done with equal
,
or with -compare-fn
if that's non-nil.
(-difference '() '()) ;; => '()
(-difference '(1 2 3) '(4 5 6)) ;; => '(1 2 3)
(-difference '(1 2 3 4) '(3 4 5 6)) ;; => '(1 2)
Return a new list containing only the elements that are members of both list
and list2
.
The test for equality is done with equal
,
or with -compare-fn
if that's non-nil.
(-intersection '() '()) ;; => '()
(-intersection '(1 2 3) '(4 5 6)) ;; => '()
(-intersection '(1 2 3 4) '(3 4 5 6)) ;; => '(3 4)
Return a new list with all duplicates removed.
The test for equality is done with equal
,
or with -compare-fn
if that's non-nil.
Alias: -uniq
(-distinct '()) ;; => '()
(-distinct '(1 2 2 4)) ;; => '(1 2 4)
Return a list with x
repeated n
times.
Returns nil if n
is less than 1.
(-repeat 3 :a) ;; => '(:a :a :a)
(-repeat 1 :a) ;; => '(:a)
(-repeat 0 :a) ;; => nil
Makes a new list from the elements of args
.
The last 2 members of args
are used as the final cons of the
result so if the final member of args
is not a list the result is
a dotted list.
(-cons* 1 2) ;; => '(1 . 2)
(-cons* 1 2 3) ;; => '(1 2 . 3)
(-cons* 1) ;; => 1
Returns a new list of all elements in list
separated by sep
.
(-interpose "-" '()) ;; => '()
(-interpose "-" '("a")) ;; => '("a")
(-interpose "-" '("a" "b" "c")) ;; => '("a" "-" "b" "-" "c")
Returns a new list of the first item in each list, then the second etc.
(-interleave '(1 2) '("a" "b")) ;; => '(1 "a" 2 "b")
(-interleave '(1 2) '("a" "b") '("A" "B")) ;; => '(1 "a" "A" 2 "b" "B")
(-interleave '(1 2 3) '("a" "b")) ;; => '(1 "a" 2 "b")
Zip the two lists list1
and list2
using a function fn
. This
function is applied pairwise taking as first argument element of
list1
and as second argument element of list2
at corresponding
position.
The anaphoric form --zip-with
binds the elements from list1
as it
,
and the elements from list2
as other
.
(-zip-with '+ '(1 2 3) '(4 5 6)) ;; => '(5 7 9)
(-zip-with 'cons '(1 2 3) '(4 5 6)) ;; => '((1 . 4) (2 . 5) (3 . 6))
(--zip-with (concat it " and " other) '("Batman" "Jekyll") '("Robin" "Hyde")) ;; => '("Batman and Robin" "Jekyll and Hyde")
Zip the two lists together. Return the list where elements
are cons pairs with car being element from list1
and cdr being
element from list2
. The length of the returned list is the
length of the shorter one.
(-zip '(1 2 3) '(4 5 6)) ;; => '((1 . 4) (2 . 5) (3 . 6))
(-zip '(1 2 3) '(4 5 6 7)) ;; => '((1 . 4) (2 . 5) (3 . 6))
(-zip '(1 2 3 4) '(4 5 6)) ;; => '((1 . 4) (2 . 5) (3 . 6))
Returns the first x in list
where (pred
x) is non-nil, else nil.
To get the first item in the list no questions asked, use car
.
(-first 'even? '(1 2 3)) ;; => 2
(-first 'even? '(1 3 5)) ;; => nil
(--first (> it 2) '(1 2 3)) ;; => 3
Return the last x in list
where (pred
x) is non-nil, else nil.
(-last 'even? '(1 2 3 4 5 6 3 3 3)) ;; => 6
(-last 'even? '(1 3 7 5 9)) ;; => nil
(--last (> (length it) 3) '("a" "looong" "word" "and" "short" "one")) ;; => "short"
Returns the first item of list
, or nil on an empty list.
(-first-item '(1 2 3)) ;; => 1
(-first-item nil) ;; => nil
Returns the first item of list
, or nil on an empty list.
(-last-item '(1 2 3)) ;; => 3
(-last-item nil) ;; => nil
Sort list
, stably, comparing elements using comparator
.
Returns the sorted list. list
is not
modified by side effects.
comparator
is called with two elements of list
, and should return non-nil
if the first element should sort before the second.
(-sort '< '(3 1 2)) ;; => '(1 2 3)
(-sort '> '(3 1 2)) ;; => '(3 2 1)
(--sort (< it other) '(3 1 2)) ;; => '(1 2 3)
Threads the expr through the forms. Inserts 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, inserts the first form as the
second item in second form, etc.
(-> "Abc") ;; => "Abc"
(-> "Abc" (concat "def")) ;; => "Abcdef"
(-> "Abc" (concat "def") (concat "ghi")) ;; => "Abcdefghi"
Threads the expr through the forms. Inserts 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, inserts the first form as the
last item in second form, etc.
(->> "Abc" (concat "def")) ;; => "defAbc"
(->> "Abc" (concat "def") (concat "ghi")) ;; => "ghidefAbc"
(->> 5 (- 8)) ;; => 3
Threads the expr through the forms. Inserts x
at the position
signified by the token it
in the first form. If there are more
forms, inserts the first form at the position signified by it
in in second form, etc.
(--> "def" (concat "abc" it "ghi")) ;; => "abcdefghi"
(--> "def" (concat "abc" it "ghi") (upcase it)) ;; => "ABCDEFGHI"
(--> "def" (concat "abc" it "ghi") upcase) ;; => "ABCDEFGHI"
If val
evaluates to non-nil, bind it to var
and execute body.
var-val
should be a (var
val
) pair.
(-when-let (match-index (string-match "d" "abcd")) (+ match-index 2)) ;; => 5
(--when-let (member :b '(:a :b :c)) (cons :d it)) ;; => '(:d :b :c)
(--when-let (even? 3) (cat it :a)) ;; => nil
If all vals
evaluate to true, bind them to their corresponding
vars
and execute body. vars-vals
should be a list of (var
val
)
pairs (corresponding to bindings of let*
).
(-when-let* ((x 5) (y 3) (z (+ y 4))) (+ x y z)) ;; => 15
(-when-let* ((x 5) (y nil) (z 7)) (+ x y z)) ;; => nil
If val
evaluates to non-nil, bind it to var
and do then
,
otherwise do else
. var-val
should be a (var
val
) pair.
(-if-let (match-index (string-match "d" "abc")) (+ match-index 3) 7) ;; => 7
(--if-let (even? 4) it nil) ;; => t
If all vals
evaluate to true, bind them to their corresponding
vars
and do then
, otherwise do else
. vars-vals
should be a list
of (var
val
) pairs (corresponding to the bindings of let*
).
(-if-let* ((x 5) (y 3) (z 7)) (+ x y z) "foo") ;; => 15
(-if-let* ((x 5) (y nil) (z 7)) (+ x y z) "foo") ;; => "foo"
Calls fn
with every item in list
. Returns nil, used for side-effects only.
(let (s) (-each '(1 2 3) (lambda (item) (setq s (cons item s))))) ;; => nil
(let (s) (-each '(1 2 3) (lambda (item) (setq s (cons item s)))) s) ;; => '(3 2 1)
(let (s) (--each '(1 2 3) (setq s (cons it s))) s) ;; => '(3 2 1)
Calls fn
with every item in list
while (pred
item) is non-nil.
Returns nil, used for side-effects only.
(let (s) (-each-while '(2 4 5 6) 'even? (lambda (item) (!cons item s))) s) ;; => '(4 2)
(let (s) (--each-while '(1 2 3 4) (< it 3) (!cons it s)) s) ;; => '(2 1)
Repeatedly calls fn
(presumably for side-effects) passing in integers from 0 through n-1.
(let (s) (-dotimes 3 (lambda (n) (!cons n s))) s) ;; => '(2 1 0)
(let (s) (--dotimes 5 (!cons it s)) s) ;; => '(4 3 2 1 0)
Destructive: Sets cdr
to the cons of car
and cdr
.
(let (l) (!cons 5 l) l) ;; => '(5)
(let ((l '(3))) (!cons 5 l) l) ;; => '(5 3)
Destructive: Sets list
to the cdr of list
.
(let ((l '(3))) (!cdr l) l) ;; => '()
(let ((l '(3 5))) (!cdr l) l) ;; => '(5)
These combinators require Emacs 24 for its lexical scope. So they are offered in a separate package: dash-functional
.
Takes a function fn
and fewer than the normal arguments to fn
,
and returns a fn that takes a variable number of additional args
.
When called, the returned function calls fn
with args
first and
then additional args.
(funcall (-partial '- 5) 3) ;; => 2
(funcall (-partial '+ 5 2) 3) ;; => 10
Takes a function fn
and fewer than the normal arguments to fn
,
and returns a fn that takes a variable number of additional args
.
When called, the returned function calls fn
with the additional
args first and then args
.
(funcall (-rpartial '- 5) 8) ;; => 3
(funcall (-rpartial '- 5 2) 10) ;; => 3
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).
(funcall (-juxt '+ '-) 3 5) ;; => '(8 -2)
(-map (-juxt 'identity 'square) '(1 2 3)) ;; => '((1 1) (2 4) (3 9))
Changes an n-arity function fn
to a 1-arity function that
expects a list with n items as arguments
(-map (-applify '+) '((1 1 1) (1 2 3) (5 5 5))) ;; => '(3 6 15)
(-map (-applify (lambda (a b c) (\` ((\, a) ((\, b) ((\, c))))))) '((1 1 1) (1 2 3) (5 5 5))) ;; => '((1 (1 (1))) (1 (2 (3))) (5 (5 (5))))
(funcall (-applify '<) '(3 6)) ;; => t
Return a function of two arguments that first applies
transformer
to each of them and then applies operator
on the
results (in the same order).
In types: (b -> b -> c) -> (a -> b) -> a -> a -> c
(-sort (-on '< 'length) '((1 2 3) (1) (1 2))) ;; => '((1) (1 2) (1 2 3))
(-min-by (-on '> 'length) '((1 2 3) (4) (1 2))) ;; => '(4)
(-min-by (-on 'string-lessp 'int-to-string) '(2 100 22)) ;; => 22
Swap the order of arguments for binary function func
.
In types: (a -> b -> c) -> b -> a -> c
(funcall (-flip '<) 2 1) ;; => t
(funcall (-flip '-) 3 8) ;; => 5
(-sort (-flip '<) '(4 3 6 1)) ;; => '(6 4 3 1)
Return a function that returns c
ignoring any additional arguments.
In types: a -> b -> a
(funcall (-const 2) 1 3 "foo") ;; => 2
(-map (-const 1) '("a" "b" "c" "d")) ;; => '(1 1 1 1)
(-sum (-map (-const 1) '("a" "b" "c" "d"))) ;; => 4
Take n-ary function and n arguments and specialize some of them. Arguments denoted by <> will be left unspecialized.
See srfi-26
for detailed description.
(funcall (-cut list 1 <> 3 <> 5) 2 4) ;; => '(1 2 3 4 5)
(-map (-cut funcall <> 5) '(1+ 1- (lambda (x) (/ 1.0 x)))) ;; => '(6 4 0.2)
(-filter (-cut < <> 5) '(1 3 5 7 9)) ;; => '(1 3)
Take an unary predicates pred
and return an unary predicate
that returns t if pred
returns nil and nil if pred
returns
non-nil.
(funcall (-not 'even?) 5) ;; => t
(-filter (-not (-partial '< 4)) '(1 2 3 4 5 6 7 8)) ;; => '(1 2 3 4)
Take list of unary predicates preds
and return an unary
predicate with argument x that returns non-nil if at least one of
the preds
returns non-nil on x.
In types: [a -> Bool] -> a -> Bool
(-filter (-orfn 'even? (-partial (-flip '<) 5)) '(1 2 3 4 5 6 7 8 9 10)) ;; => '(1 2 3 4 6 8 10)
(funcall (-orfn 'stringp 'even?) "foo") ;; => t
Take list of unary predicates preds
and return an unary
predicate with argument x that returns non-nil if all of the
preds
returns non-nil on x.
In types: [a -> Bool] -> a -> Bool
(funcall (-andfn (-cut < <> 10) 'even?) 6) ;; => t
(funcall (-andfn (-cut < <> 10) 'even?) 12) ;; => nil
(-filter (-andfn (-not 'even?) (-cut >= 5 <>)) '(1 2 3 4 5 6 7 8 9 10)) ;; => '(1 3 5)
Yes, please do. Pure functions in the list manipulation realm only,
please. There's a suite of tests in dev/examples.el
, so remember to add
tests for your function, or I might break it later.
You'll find the repo at:
https://github.com/magnars/dash.el
Run the tests with
./run-tests.sh
Create the docs with
./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:
cp pre-commit.sh .git/hooks/pre-commit
Oh, and don't edit README.md
directly, it is auto-generated.
Change readme-template.md
or examples-to-docs.el
instead.
- Add indexing operations (Matus Goljer)
- Split out
dash-functional.el
(Matus Goljer) - Add
-andfn
,-orfn
,-not
,-cut
,-const
,-flip
and-on
. (Matus Goljer) - Fix
-min
,-max
,-min-by
and-max-by
(Matus Goljer)
- Add
-first-item
and-last-item
(Wilfred Hughes)
- Add
-rotate
(Matus Goljer)
- Add
-min
,-max
,-min-by
and-max-by
(Johan Andersson)
- Add
-sum
and-product
(Johan Andersson)
- Add
-sort
- Add
-reduce-r
(Matus Goljer) - Add
-reduce-r-from
(Matus Goljer)
- Add
-partition-in-steps
- Add
-partition-all-in-steps
- Add
-last
(Matus Goljer) - Add
-insert-at
(Emanuel Evans) - Add
-when-let
and-if-let
(Emanuel Evans) - Add
-when-let*
and-if-let*
(Emanuel Evans) - Some bugfixes
- Matus Goljer contributed lots of features and functions.
- Takafumi Arakaki contributed
-group-by
. - tali713 is the author of
-applify
. - Víctor M. Valenzuela contributed
-repeat
. - Nic Ferrier contributed
-cons*
. - Wilfred Hughes contributed
-slice
,-first-item
and-last-item
. - Emanuel Evans contributed
-if-let
,-when-let
and-insert-at
. - Johan Andersson contributed
-sum
and-product
.
Thanks!
Copyright (C) 2012-2013 Magnar Sveen
Authors: Magnar Sveen [email protected] Keywords: lists
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 http://www.gnu.org/licenses/.