6. Collection Functions

The lists/ and maps/ namespaces provide operations for each collection type. The collections/ namespace provides operations shared by lists and maps. Functions that change a collection change it in place and return it; functions that make a new collection share nested values with their inputs. Unless stated otherwise, operations that make a new collection accept null as an empty collection, and operations that change a collection require a target of the stated type. Map keys are strings.

Table of Contents

6.1. List functions: lists/ ↑

6.1.1. lists/mapcat ↑

Function

(lists/mapcat f list lists*) → list

Applies f to corresponding elements of list and any additional lists, then concatenates the result lists one level deep. Stops at the shortest input list.

DUST
(lists/mapcat (fn [x] [.x .x]) [a b])
(lists/mapcat (fn [x] [.x]) [])
(lists/mapcat (fn [x] (if (= .x 0) [] [.x])) [0 1 0 2])
(lists/mapcat (fn [x] [.x]) null)
(lists/mapcat (fn [x] null) [a b])
(lists/mapcat (fn [a b] [.a .b]) [1 2] [a])
(lists/mapcat (fn [a b c] [.a .b .c]) [1 2] [a b] [false null])
(lists/mapcat :fn/identity [[[a]] [[b]]])
(lists/mapcat :fn/identity [[null false] [] [0]])
=
DUST Result
[[a a b b] [] [1 2] [] [] [1 a] [1 a false 2 b null] [[a] [b]] [null false 0]]
DUST
{list (lists/mapcat :fn/identity abc)
 missing (lists/mapcat)
 result (lists/mapcat :fn/identity [1])
 transducer (lists/mapcat :fn/identity)}
→
Evaluation cases
#cases [{output #err <mismatch type>
         select list}
        {output #err <mismatch type>
         select result}
        {output #err <arity mismatch>
         select missing}
        {output #err <arity mismatch>
         select transducer}]

6.1.2. lists/keep ↑

Function

(lists/keep f list) → list

Returns the results of applying f to each element of list, excluding null but preserving false and input order.

DUST
(lists/keep (fn [x] (if (comparison/identical? .x 0) null .x)) [0 1 false 2])
(lists/keep :fn/identity [null false 1])
(lists/keep :fn/identity [])
(lists/keep :fn/identity null)
(lists/keep :fn/identity [null null])
(lists/keep :fn/identity [false 0 "" [] {}])
(lists/keep (fn [x] (* .x 2)) [1 2 3])
(lists/keep (fn [x] [.x]) [a b])
=
DUST Result
[[1 false 2] [false 1] [] [] [] [false 0 "" [] {}] [2 4 6] [[a] [b]]]
DUST
{extra (lists/keep :fn/identity [a] [b])
 list (lists/keep :fn/identity abc)
 missing (lists/keep)
 transducer (lists/keep :fn/identity)}
→
Evaluation cases
#cases [{output #err <mismatch type>
         select list}
        {output #err <arity mismatch>
         select missing}
        {output #err <arity mismatch>
         select transducer}
        {output #err <arity mismatch>
         select extra}]

6.1.3. lists/nth ↑

Function

(lists/nth list index default?) → value

Returns the element at the nonnegative, zero-based integer index. An out-of-range index returns default if supplied; otherwise it is an error. A negative index is an error even when a default is supplied.

DUST
(lists/nth [a b c] 0)
(lists/nth [a b c] 2)
(lists/nth [] 0 missing)
=
DUST Result
a
c
missing
DUST
(lists/nth [] 0)
=
DUST Result
#err <invalid value>

6.1.4. lists/second ↑

Function

(lists/second list) → value

Returns the second element of list, or null if list has fewer than two elements.

DUST
(lists/second [a b c])
(lists/second [a])
(lists/second [])
(lists/second null)
(lists/second [a false])
(lists/second [a null c])
(lists/second [a {name Ada}])
(lists/second [a [b c]])
=
DUST Result
b
null
null
null
false
null
{name Ada}
[b c]
DUST
{boolean (lists/second false)
 extra (lists/second [a b] fallback)
 map (lists/second {a 1 b 2})
 missing (lists/second)
 number (lists/second 2)
 string (lists/second ab)}
→
Evaluation cases
#cases [{output #err <mismatch type>
         select string}
        {output #err <mismatch type>
         select map}
        {output #err <mismatch type>
         select number}
        {output #err <mismatch type>
         select boolean}
        {output #err <arity mismatch>
         select missing}
        {output #err <arity mismatch>
         select extra}]

6.1.5. lists/last ↑

Function

(lists/last list) → value

Returns the last element, or null for an empty list.

DUST
(lists/last [a b])
(lists/last [])
(lists/last [false null])
=
DUST Result
b
null
null

6.1.6. lists/append ↑

Function

(lists/append list values*) → list

Appends values to list in place as individual elements and returns the same list. Values are stored without copying. With no additional values, leaves list unchanged. list must be a list, not null or a pointer.

DUST
(let [xs [a]] [(lists/append .xs b) .xs])
(let [xs []] [(lists/append .xs null false) .xs])
(let [xs [1 2]] [(lists/append .xs 3 4) .xs])
=
DUST Result
[[[a b] [a b]] [[null false] [null false]] [[1 2 3 4] [1 2 3 4]]]
DUST
(lists/append [1 2] 3 4)
(lists/append [] null false)
(let [xs [a]] [(lists/append (collections/copy .xs) b) .xs])
=
DUST Result
[[1 2 3 4] [null false] [[a b] [a]]]

6.1.7. lists/concat ↑

Function

(lists/concat lists*) → list

Returns a fresh list containing the elements of each input list, in order. With no inputs, returns an empty list.

DUST
(lists/concat [1] [2 3])
(lists/concat)
(lists/concat null [a] [])
=
DUST Result
[[1 2 3] [] [a]]

6.1.8. lists/interpose ↑

Function

(lists/interpose separator list) → list

Returns a fresh list with separator between adjacent elements of list.

DUST
(lists/interpose x [a b c])
(lists/interpose x [a])
(lists/interpose x [])
(lists/interpose x null)
(lists/interpose null [a b])
(lists/interpose false [a b])
(lists/interpose [x y] [[a] [b]])
(let [list [a b]] [(lists/interpose x .list) .list])
=
DUST Result
[[a x b x c] [a] [] [] [a null b] [a false b] [[a] [x y] [b]] [[a x b] [a b]]]
DUST
{boolean (lists/interpose x false)
 extra-argument (lists/interpose x [a b] [c])
 map (lists/interpose x {a 1})
 missing-list (lists/interpose x)
 no-arguments (lists/interpose)
 string (lists/interpose x abc)}
→
Evaluation cases
#cases [{output #err <mismatch type>
         select string}
        {output #err <mismatch type>
         select map}
        {output #err <mismatch type>
         select boolean}
        {output #err <arity mismatch>
         select no-arguments}
        {output #err <arity mismatch>
         select missing-list}
        {output #err <arity mismatch>
         select extra-argument}]

6.1.9. lists/interleave ↑

Function

(lists/interleave) → list
(lists/interleave list) → list
(lists/interleave list1 list2) → list
(lists/interleave list1 list2 lists*) → list

Returns a fresh list taking one element from each input list in turn, stopping at the shortest list. Returns [] with no inputs and a shallow copy with one.

DUST
(lists/interleave [a b] [1 2])
(lists/interleave [a b c] [1])
(lists/interleave [a b] [1 2] [x y])
(lists/interleave [] [1 2])
(lists/interleave)
(lists/interleave [a b])
(lists/interleave [])
(lists/interleave null)
(lists/interleave [a b] null)
(lists/interleave [a] [1 2])
(lists/interleave [a b] [1 2] [x])
(lists/interleave [a b] [1 2] [x y] [true false])
(lists/interleave [null false] [[a] {b 2}])
(let [list [a b]] [(lists/interleave .list) .list])
=
DUST Result
[[a 1 b 2] [a 1] [a 1 x b 2 y] []
 [] [a b] [] []
 [] [a 1] [a 1 x]
 [a 1 x true b 2 y false] [null [a] false {b 2}] [[a b] [a b]]]
DUST
{additional (lists/interleave [1] [2] abc)
 boolean (lists/interleave false)
 first (lists/interleave abc [1])
 map (lists/interleave {a 1})
 number (lists/interleave 1)
 second (lists/interleave [1] abc)
 string (lists/interleave abc)}
→
Evaluation cases
#cases [{output #err <mismatch type>
         select string}
        {output #err <mismatch type>
         select map}
        {output #err <mismatch type>
         select number}
        {output #err <mismatch type>
         select boolean}
        {output #err <mismatch type>
         select first}
        {output #err <mismatch type>
         select second}
        {output #err <mismatch type>
         select additional}]

6.1.10. lists/flatten ↑

Function

(lists/flatten list) → list

Returns a list of the non-list elements in list, recursively expanding nested lists in order. Empty lists contribute no elements. Non-list elements, including maps, strings, and null, are kept unchanged. list must be a list, otherwise produces #err <mismatch type>. Missing or extra arguments produce #err <arity mismatch>.

DUST
(lists/flatten [1 [2 [3]] [] 4])
(lists/flatten [1 null [2]])
(lists/flatten [])
(lists/flatten [[] [[]] []])
(lists/flatten [1 2 3])
(lists/flatten [[a a] [false [true]]])
(lists/flatten
  [{items [1 [2]]}
   [
     hello world
     #custom [3 [4]]]
   null])
=
DUST Result
[[1 2 3 4]
 [1 null 2]
 []
 []
 [1 2 3]
 [a a false true]
 [
   {items [1 [2]]}
   hello world
   #custom [3 [4]]
   null]]
DUST
{boolean-input (lists/flatten false)
 extra-argument (lists/flatten [1] [2])
 integer-input (lists/flatten 42)
 map-input (lists/flatten {items [1 2]})
 missing-argument (lists/flatten)
 null-input (lists/flatten null)
 string-input (lists/flatten abc)
 tagged-input (lists/flatten #custom [1 2])}
→
Evaluation cases
#cases [{output #err <mismatch type>
         select null-input}
        {output #err <mismatch type>
         select string-input}
        {output #err <mismatch type>
         select map-input}
        {output #err <mismatch type>
         select integer-input}
        {output #err <mismatch type>
         select boolean-input}
        {output #err <mismatch type>
         select tagged-input}
        {output #err <arity mismatch>
         select missing-argument}
        {output #err <arity mismatch>
         select extra-argument}]

6.1.11. lists/slice ↑

Function

(lists/slice list start end?) → list

Returns a fresh list from start up to, but excluding, end. Indexes are nonnegative, zero-based integers. An omitted end means the list's length. Indexes beyond the length are clamped, and an end before the start produces an empty list.

DUST
(lists/slice [a b c] 1 3)
(lists/slice [a b c] 1)
(lists/slice [a b] 1 0)
(lists/slice [a b] 0 9)
=
DUST Result
[[b c] [b c] [] [a b]]
DUST
(lists/slice [a] -1)
=
DUST Result
#err <invalid value>

6.1.12. lists/take ↑

Function

(lists/take n list) → list

Returns a fresh list of the first n elements of list, or all elements if fewer are available.

DUST
(lists/take 2 [a b c d])
(lists/take 5 [a b])
(lists/take 0 [a b])
(lists/take 2 [])
(lists/take -1 [a b])
(lists/take 2 null)
(lists/take 1.5 [a b c])
(lists/take -1.5 [a b])
(lists/take 2 [null false c])
(let [list [a b c]] [(lists/take 2 .list) .list])
=
DUST Result
[[a b] [a b] [] [] [] [] [a b] [] [null false] [[a b] [a b c]]]
DUST
{count (lists/take two [a b])
 extra (lists/take 1 [a] [b])
 list (lists/take 1 abc)
 missing (lists/take)
 transducer (lists/take 1)}
→
Evaluation cases
#cases [{output #err <mismatch type>
         select count}
        {output #err <mismatch type>
         select list}
        {output #err <arity mismatch>
         select missing}
        {output #err <arity mismatch>
         select transducer}
        {output #err <arity mismatch>
         select extra}]

6.1.13. lists/take-while ↑

Function

(lists/take-while predicate list) → list

Returns the leading elements of list for which predicate is truthy, stopping at the first falsey result.

DUST
(lists/take-while (fn [x] (< .x 3)) [1 2 3 1])
(lists/take-while :fn/identity [1 false 2])
(lists/take-while :fn/identity [])
(lists/take-while :fn/identity null)
(lists/take-while :fn/identity [false 1])
(lists/take-while :fn/identity [0 "" [] null 1])
(lists/take-while (fn [x] true) [null false])
(lists/take-while (fn [x] (< .x 3)) [1 2 3 invalid])
=
DUST Result
[[1 2] [1] [] [] [] [0 "" []] [null false] [1 2]]
DUST
{extra (lists/take-while :fn/identity [a] [b])
 list (lists/take-while :fn/identity abc)
 missing (lists/take-while)
 predicate (lists/take-while 1 [a])
 transducer (lists/take-while :fn/identity)}
→
Evaluation cases
#cases [{output #err <expected function>
         select predicate}
        {output #err <mismatch type>
         select list}
        {output #err <arity mismatch>
         select missing}
        {output #err <arity mismatch>
         select transducer}
        {output #err <arity mismatch>
         select extra}]

6.1.14. lists/drop ↑

Function

(lists/drop n list) → list

Returns a fresh list excluding the first n elements of list.

DUST
(lists/drop 2 [a b c d])
(lists/drop 5 [a b])
(lists/drop 0 [a b])
(lists/drop 2 [])
(lists/drop -1 [a b])
(lists/drop 2 null)
(lists/drop 1.5 [a b c])
(lists/drop -1.5 [a b])
(lists/drop 1 [a null false])
(let [list [a b c]] [(lists/drop 1 .list) .list])
=
DUST Result
[[c d] [] [a b] [] [a b] [] [c] [a b] [null false] [[b c] [a b c]]]
DUST
{count (lists/drop two [a b])
 extra (lists/drop 1 [a] [b])
 list (lists/drop 1 abc)
 missing (lists/drop)
 transducer (lists/drop 1)}
→
Evaluation cases
#cases [{output #err <mismatch type>
         select count}
        {output #err <mismatch type>
         select list}
        {output #err <arity mismatch>
         select missing}
        {output #err <arity mismatch>
         select transducer}
        {output #err <arity mismatch>
         select extra}]

6.1.15. lists/drop-while ↑

Function

(lists/drop-while predicate list) → list

Returns list from the first element for which predicate is falsey, skipping the preceding elements.

DUST
(lists/drop-while (fn [x] (< .x 3)) [1 2 3 1])
(lists/drop-while :fn/identity [1 false 2])
(lists/drop-while :fn/identity [])
(lists/drop-while :fn/identity null)
(lists/drop-while :fn/identity [false 1])
(lists/drop-while :fn/identity [0 "" [] null 1])
(lists/drop-while (fn [x] true) [null false])
(lists/drop-while (fn [x] (< .x 3)) [1 2 3 invalid])
=
DUST Result
[[3 1] [false 2] [] [] [false 1] [null 1] [] [3 invalid]]
DUST
{extra (lists/drop-while :fn/identity [a] [b])
 list (lists/drop-while :fn/identity abc)
 missing (lists/drop-while)
 predicate (lists/drop-while 1 [a])
 transducer (lists/drop-while :fn/identity)}
→
Evaluation cases
#cases [{output #err <expected function>
         select predicate}
        {output #err <mismatch type>
         select list}
        {output #err <arity mismatch>
         select missing}
        {output #err <arity mismatch>
         select transducer}
        {output #err <arity mismatch>
         select extra}]

6.1.16. lists/partition ↑

Function

(lists/partition n list) → list
(lists/partition n step list) → list

Returns groups of up to n elements from list, starting step elements apart and including short trailing groups. step defaults to n.

DUST
(lists/partition 2 [a b c d e])
(lists/partition 2 1 [a b c])
(lists/partition 3 [])
(lists/partition 3 [a])
(lists/partition 2 3 [a b c d e f g])
(lists/partition 3 1 [a b c d])
(lists/partition 1 [null false [a]])
(lists/partition 2 null)
(lists/partition 2 1 null)
(lists/partition 9223372036854775807 [a b])
(lists/partition 2 9223372036854775807 [a b c])
=
DUST Result
[[[a b] [c d] [e]] [[a b] [b c] [c]] [] [[a]]
 [[a b] [d e] [g]] [[a b c] [b c d] [c d] [d]] [[null] [false] [[a]]] []
 [] [[a b]] [[a b]]]
DUST
{empty-zero (lists/partition 0 [])
 extra (lists/partition 2 1 [] [])
 fractional-size (lists/partition 1.5 [a])
 fractional-step (lists/partition 2 1.5 [a])
 list (lists/partition 2 abc)
 missing (lists/partition)
 negative-size (lists/partition -1 [a])
 negative-step (lists/partition 2 -1 [a])
 transducer (lists/partition 2)
 zero-size (lists/partition 0 [a])
 zero-step (lists/partition 2 0 [a])}
→
Evaluation cases
#cases [{output #err <invalid value>
         select zero-size}
        {output #err <invalid value>
         select negative-size}
        {output #err <invalid value>
         select zero-step}
        {output #err <invalid value>
         select negative-step}
        {output #err <invalid value>
         select empty-zero}
        {output #err <mismatch type>
         select fractional-size}
        {output #err <mismatch type>
         select fractional-step}
        {output #err <mismatch type>
         select list}
        {output #err <arity mismatch>
         select missing}
        {output #err <arity mismatch>
         select transducer}
        {output #err <arity mismatch>
         select extra}]

6.1.17. lists/reverse ↑

Function

(lists/reverse list) → list

Reverses list in place and returns the same list, without copying the elements. list must be a list, not null or a pointer.

DUST
(let [xs [a b c]] [(lists/reverse .xs) .xs])
(let [xs []] [(lists/reverse .xs) .xs])
(let [xs [a]] [(lists/reverse .xs) .xs])
=
DUST Result
[[[c b a] [c b a]] [[] []] [[a] [a]]]
DUST
(lists/reverse [a b c])
(lists/reverse [])
(lists/reverse [null false])
=
DUST Result
[[c b a] [] [false null]]

6.1.18. lists/filter ↑

Function

(lists/filter predicate list) → list

Calls predicate on each element, from left to right, and returns the elements whose results are truthy. Retains their input order.

DUST
(lists/filter :boolean [null false 0 a])
(lists/filter (fn [x] (= .x 2)) [1 2 2 3])
(lists/filter :boolean [])
=
DUST Result
[[0 a] [2 2] []]

6.1.19. lists/any? ↑

Function

(lists/any? predicate list) → boolean

Returns true at the first truthy predicate result without visiting later elements. Returns false for an empty list.

DUST
(lists/any? :boolean [null false a])
(lists/any? :boolean [])
(lists/any? (fn [x] (if .x true (/ 1 0))) [true false])
=
DUST Result
true
false
true

6.1.20. lists/every? ↑

Function

(lists/every? predicate list) → boolean

Returns false at the first falsey predicate result without visiting later elements. Returns true for an empty list.

DUST
(lists/every? :boolean [0 a])
(lists/every? :boolean [])
(lists/every? (fn [x] (if .x (/ 1 0) false)) [false true])
=
DUST Result
true
true
false

6.1.21. lists/some ↑

Function

(lists/some f list) → value

Returns the first truthy result of applying f to elements of list, without visiting later elements, or null if none matches.

DUST
(lists/some (fn [x] (get .x name)) [{} {name Ada} {name Bea}])
(lists/some :fn/identity [false null 0 7])
(lists/some :fn/identity [false null])
(lists/some :fn/identity [])
(lists/some :fn/identity null)
(lists/some :fn/identity [null false [] a])
(lists/some :fn/identity [false "" a])
(lists/some (fn [x] (if (> .x 1) {found .x} null)) [0 1 2 3])
(lists/some (fn [x] (if (= .x 2) yes null)) [1 2 invalid])
=
DUST Result
Ada
0
null
null
null
[]
""
{found 2}
yes
DUST
{extra (lists/some :fn/identity [a] [b])
 function (lists/some 1 [a])
 list (lists/some :fn/identity abc)
 missing (lists/some)
 missing-list (lists/some :fn/identity)}
→
Evaluation cases
#cases [{output #err <expected function>
         select function}
        {output #err <mismatch type>
         select list}
        {output #err <arity mismatch>
         select missing}
        {output #err <arity mismatch>
         select missing-list}
        {output #err <arity mismatch>
         select extra}]

6.1.22. lists/find-first ↑

Function

(lists/find-first predicate list) → value
(lists/find-first predicate list default) → value

Returns the first element of list for which predicate is truthy, or default if none matches. The default is null.

DUST
(lists/find-first (fn [x] (get .x name)) [{} {name Ada} {name Bea}])
(lists/find-first (fn [x] (comparison/identical? .x false)) [null false true])
(lists/find-first :fn/identity [null false])
(lists/find-first :fn/identity [] fallback)
(lists/find-first :fn/identity null)
(lists/find-first :fn/identity null fallback)
(lists/find-first :fn/identity [0 1])
(lists/find-first (fn [x] true) [null] fallback)
(lists/find-first (fn [x] false) [a b] false)
=
DUST Result
{name Ada}
false
null
fallback
null
fallback
0
null
false
DUST
{extra (lists/find-first :fn/identity [] fallback extra)
 list (lists/find-first :fn/identity abc)
 missing (lists/find-first)
 missing-list (lists/find-first :fn/identity)}
→
Evaluation cases
#cases [{output #err <mismatch type>
         select list}
        {output #err <arity mismatch>
         select missing}
        {output #err <arity mismatch>
         select missing-list}
        {output #err <arity mismatch>
         select extra}]

6.1.23. lists/range ↑

Function

(lists/range end) → list
(lists/range start end step?) → list

Returns integers from start up to, but excluding, end, incrementing by step. The defaults are zero for start and one for step. A negative step produces a descending range. A zero step is an error. All arguments must be integers.

DUST
(lists/range 3)
(lists/range 1 6 2)
(lists/range 3 0 -1)
(lists/range 3 0)
=
DUST Result
[[0 1 2] [1 3 5] [3 2 1] []]
DUST
(lists/range 0 3 0)
=
DUST Result
#err <invalid value>

6.1.24. lists/repeat ↑

Function

(lists/repeat count value) → list

Returns a list containing value the specified number of times. count must be a nonnegative integer. Values are reused rather than deep copied.

DUST
(lists/repeat 3 x)
(lists/repeat 0 x)
(lists/repeat 2 null)
=
DUST Result
[[x x x] [] [null null]]
DUST
(lists/repeat -1 x)
=
DUST Result
#err <invalid value>

6.1.25. lists/sort-by ↑

Function

(lists/sort-by f list) → list
(lists/sort-by f comparator list) → list

Sorts list in place, stably, by the keys returned by f, and returns the same list. The list's order changes only after key extraction and all comparisons succeed. list must be a list, not null or a pointer. Calls f once per element, from left to right, before making comparisons. The key function must be an ordinary function and must not change the input list or its elements. Uses sort ordering, or the supplied comparator applied to the keys. Equal keys keep their input order. Elements are shared without copying. Key-function errors stop processing and are returned.

DUST
(lists/sort-by :first [[b 1] [a 2] [b 3]])
(lists/sort-by :count [abc a ab])
(lists/sort-by :first [])
(let
  [m {seen []}]
  [(lists/sort-by (fn [x] (patch .m {seen (lists/append (get .m seen) .x)}) .x) [3 2 1]) (get .m seen)])
→
Canonical DUST
(lists/sort-by :first [[b 1] [a 2] [b 3]])
(lists/sort-by :count [abc a ab])
(lists/sort-by :first [])
(let
  [m {seen []}]
  [(lists/sort-by (fn [x] (patch .m {seen (lists/append (get .m seen) .x)}) .x) [3 2 1])
   (get .m seen)])
=
DUST Result
[[[a 2] [b 1] [b 3]] [a ab abc] [] [[1 2 3] [3 2 1]]]
DUST
(lists/sort-by :first [[1 a] [1.0 b]])
=
DUST Result
#err <mismatch type>
DUST
(let [xs [ab c def]] [(lists/sort-by :count .xs) .xs])
(let [xs []] [(lists/sort-by :count .xs) .xs])
(let [xs [ab cd e]] [(lists/sort-by :count .xs) .xs])
=
DUST Result
[[[c ab def] [c ab def]] [[] []] [[e ab cd] [e ab cd]]]

6.1.26. lists/partition-by ↑

Function

(lists/partition-by f list) → list

Returns consecutive groups from list, starting a new group whenever f returns a different value.

DUST
(lists/partition-by :fn/identity [a a b a])
(lists/partition-by :fn/identity [])
(lists/partition-by (fn [x] (math/zero? .x)) [0 0 1 2 0])
(lists/partition-by :fn/identity null)
(lists/partition-by :fn/identity [null null false false null])
(lists/partition-by :fn/identity [[a] [a] [b]])
(lists/partition-by (fn [x] same) [a b c])
(lists/partition-by :fn/identity [1 1.0 1])
(lists/partition-by :fn/identity [a b c])
=
DUST Result
[[[a a] [b] [a]] [] [[0 0] [1 2] [0]]
 [] [[null null] [false false] [null]] [[[a] [a]] [[b]]]
 [[a b c]] [[1] [1.0] [1]] [[a] [b] [c]]]
DUST
{extra (lists/partition-by :fn/identity [a] [b])
 function (lists/partition-by 1 [a])
 list (lists/partition-by :fn/identity abc)
 missing (lists/partition-by)
 transducer (lists/partition-by :fn/identity)}
→
Evaluation cases
#cases [{output #err <expected function>
         select function}
        {output #err <mismatch type>
         select list}
        {output #err <arity mismatch>
         select missing}
        {output #err <arity mismatch>
         select transducer}
        {output #err <arity mismatch>
         select extra}]

6.1.27. lists/group-by ↑

Function

(lists/group-by function list) → map

Calls function on each element, from left to right. Each result must be a string and becomes a map key. Each map value is the list of input elements with that key, preserving their input order. Non-string keys are errors.

DUST
(lists/group-by :first [[a 1] [b 2] [a 3]])
(lists/group-by (fn [x] (strings/case upper .x)) [a A b])
(lists/group-by :first [])
=
DUST Result
{a [[a 1] [a 3]]
 b [[b 2]]}
{A [a A]
 B [b]}
{}
DUST
(lists/group-by :first [[1 a]])
=
DUST Result
#err <mismatch type>

6.1.28. lists/frequencies ↑

Function

(lists/frequencies strings) → map

Counts each string in the input list and returns a map from strings to integer counts. Non-string elements are errors; integer 1 is never coerced to string "1".

DUST
(lists/frequencies [a b a])
(lists/frequencies [])
(lists/frequencies [é 猫 é])
=
DUST Result
{a 2
 b 1}
{}
{é 2
 猫 1}
DUST
(lists/frequencies [1 "1"])
=
DUST Result
#err <mismatch type>

6.2. Map functions: maps/ ↑

6.2.1. maps/zipmap ↑

Function

(maps/zipmap keys values) → map

Returns a fresh map pairing string keys with values, stopping at the shorter list. Later duplicate keys win.

DUST
(maps/zipmap [a b] [1 2])
(maps/zipmap [a b c] [1])
(maps/zipmap [a a] [1 2])
(maps/zipmap [] [1])
(maps/zipmap [a] [1 2])
(maps/zipmap [a] [])
(maps/zipmap null [1])
(maps/zipmap [a] null)
(maps/zipmap [a b c] [null false [1 2]])
(maps/zipmap [a a] [1 null])
(maps/zipmap ["" "/a" a/b] [1 2 3])
=
DUST Result
{a 1
 b 2}
{a 1}
{a 2}
{}
{a 1}
{}
{}
{}
{<!b>
 a null
 c [1 2]}
{a null}
{"" 1
 /a 2
 a/b 3}
DUST
{extra-argument (maps/zipmap [a] [1] [2])
 integer-key (maps/zipmap [1] [a])
 keys-not-list (maps/zipmap a [1])
 missing-values (maps/zipmap [a])
 no-arguments (maps/zipmap)
 null-key (maps/zipmap [null] [a])
 values-not-list (maps/zipmap [a] 1)}
→
Evaluation cases
#cases [{output #err <mismatch type>
         select keys-not-list}
        {output #err <mismatch type>
         select values-not-list}
        {output #err <mismatch type>
         select integer-key}
        {output #err <mismatch type>
         select null-key}
        {output #err <arity mismatch>
         select no-arguments}
        {output #err <arity mismatch>
         select missing-values}
        {output #err <arity mismatch>
         select extra-argument}]

6.2.2. maps/select-keys ↑

Function

(maps/select-keys map keys) → map

Returns a fresh map containing the literal top-level keys in keys that are present in map.

DUST
(maps/select-keys {a 1 b 2} [b missing])
(maps/select-keys {a null} [a a])
(maps/select-keys null [a])
=
DUST Result
{b 2}
{a null}
{}
DUST
(maps/select-keys {a 1 b 2 c 3} [a c])
(maps/select-keys {/a 1 b 2} ["/a"])
(maps/select-keys {a 1} [missing a])
(maps/select-keys {/a/b 2 a {b 1}} ["/a/b"])
(maps/select-keys
  {<!b>
   a null
   c 3}
  [b a a])
(maps/select-keys null [a])
(maps/select-keys {a 1} [])
(maps/select-keys {a 1} null)
=
DUST Result
{a 1
 c 3}
{/a 1}
{a 1}
{/a/b 2}
{<!b>
 a null}
{}
{}
{}
DUST
{extra (maps/select-keys {} [] [])
 key-type (maps/select-keys {a 1} [0])
 keys (maps/select-keys {a 1} a)
 map (maps/select-keys [a] [a])
 missing (maps/select-keys)
 missing-keys (maps/select-keys {})
 path-list (maps/select-keys {a {b 1}} [[a b]])}
→
Evaluation cases
#cases [{output #err <mismatch type>
         select map}
        {output #err <mismatch type>
         select keys}
        {output #err <mismatch type>
         select key-type}
        {output #err <mismatch type>
         select path-list}
        {output #err <arity mismatch>
         select missing}
        {output #err <arity mismatch>
         select missing-keys}
        {output #err <arity mismatch>
         select extra}]

6.3. Collection paths: collections/ ↑

6.3.1. collections/update ↑

Function

(collections/update root path f args*) → collection

Replaces the value at path in root with the result of calling f on that value and args, in place, and returns the same root collection. Stores the result as put does, including container creation and list growth. A missing entry supplies null to f.

Validates the destination before calling f once, and again before storing the result. The callback must be an ordinary function, otherwise produces #err <expected function>. A callback error is returned without storing a replacement. The callback receives the existing value without copying, and its side effects are not undone. The root must be a map or list, not null. An empty path produces #err <invalid value>.

DUST
(let [record {score 2}] (collections/update .record score :+ 3) .record)
(let [record {user {score 2}}] (collections/update .record [user score] :+ 3) .record)
(let [record {tags [old]}] (collections/update .record tags :lists/append new) .record)
=
DUST Result
{score 5}
{user {score 5}}
{tags [old new]}
DUST
(let
  [record {score 2} updated (collections/update (collections/copy .record) score :+ 3)]
  [.record .updated])
(let
  [record
   {user {score 2}}
   updated
   (collections/update (collections/copy .record) [user score] :+ 3)]
  [.record .updated])
(let
  [record
   {user {score 2}}
   updated
   (collections/update (collections/copy .record shallow) [user score] :+ 3)]
  [.record .updated])
=
DUST Result
[[{score 2} {score 5}] [{user {score 2}} {user {score 5}}] [{user {score 5}} {user {score 5}}]]

6.3.2. collections/copy ↑

Function

(collections/copy value) → value
(collections/copy value shallow) → value

Returns a copy of value that changes to either leave the other unchanged. Copies every list and map reachable from value. A list or map reached more than once is copied once, so collections shared within value stay shared within the copy, and cycles stay cycles. With the mode shallow, copies only the top-level list or map; its members are shared. Other values do not change and are returned as they are.

A mode other than shallow produces #err <invalid value>, and a mode that is not a string #err <mismatch type>. Nesting deeper than the depth limit produces #err <limit resource>.

DUST
(let [m {a {b 1}} c (collections/copy .m)] (put .c ["a" "b"] 2) [.m .c])
(let [m {a {b 1}} c (collections/copy .m shallow)] (put .c ["a" "b"] 2) (put .c "x" 3) [.m .c])
(let [l [1 [2]] c (collections/copy .l)] (lists/append .c 3) (lists/append (get .c 1) 4) [.l .c])
(let [s {n 1} m {a .s b .s} c (collections/copy .m)] (put .c ["a" "n"] 2) [(get .c ["b" "n"]) (get .m ["a" "n"])])
[(collections/copy 5) (collections/copy "x") (collections/copy null)]
(collections/copy {a 1} deep)
(collections/copy {a 1} 5)
(let [m {a 1}] (put .m "self" .m) (let [c (collections/copy .m)] [(comparison/identical? (get .c "self") .c) (comparison/identical? (get .c "self") .m)]))
→
Canonical DUST
(let [m {a {b 1}} c (collections/copy .m)] (put .c [a b] 2) [.m .c])
(let [m {a {b 1}} c (collections/copy .m shallow)] (put .c [a b] 2) (put .c x 3) [.m .c])
(let [l [1 [2]] c (collections/copy .l)] (lists/append .c 3) (lists/append (get .c 1) 4) [.l .c])
(let
  [s {n 1} m {a .s b .s} c (collections/copy .m)]
  (put .c [a n] 2)
  [(get .c [b n]) (get .m [a n])])
[(collections/copy 5) (collections/copy x) (collections/copy null)]
(collections/copy {a 1} deep)
(collections/copy {a 1} 5)
(let
  [m {a 1}]
  (put .m self .m)
  (let
    [c (collections/copy .m)]
    [(comparison/identical? (get .c self) .c) (comparison/identical? (get .c self) .m)]))
=
DUST Result
[[{a {b 1}} {a {b 2}}]
 [{a {b 2}} {a {b 2} x 3}]
 [[1 [2]] [1 [2 4] 3]]
 [2 1]
 [5 x null]
 #err {<invalid value>
       message "unknown copy mode"}
 #err {<mismatch type>
       message "copy mode must be a string"}
 [true false]]