logos.seq reference

Copy Markdown

Every public, documented Var in logos.seq, pulled live from its own docstring, each with a real, freshly-evaluated example and its own source. For prose/narrative explanation and worked examples, see the language reference; for everything else generated (the overview, special forms, primitives, and every other stdlib namespace), see the other pages in this "Stdlib Reference" section.

assoc-in

fn -- (assoc-in coll ks v)

Nested assoc: (assoc-in {:a {:b 1}} [:a :b] 2) => {:a {:b 2}}. Creates intermediate maps as needed (assoc's own nil-treated-as- {} behavior, recursively).

Example:

(assoc-in {:a {:b 1}} [:a :b] 2)
;;=> {:a {:b 2}}

Source:

(defn assoc-in
  [coll ks v]
  (let [ks-list (to-list ks)]
    (cond
      (empty? ks-list) v
      (empty? (rest ks-list)) (assoc coll (first ks-list) v)
      true
      (assoc coll (first ks-list) (assoc-in (get coll (first ks-list)) (rest ks-list) v)))))

conj

fn -- (conj coll & xs)

Adds xs to coll, one at a time, in the position natural for coll's own shape: prepend for a list/nil, append for a vector, union into a set (a sorted-set stays sorted). Each of xs for a map target must be a 2-element (k v) list, assoc'd in (a sorted-map stays sorted, ordered by its own comparator).

Example:

(conj [1 2] 3 4)
;;=> [1 2 3 4]

Source:

(defn conj
  [coll & xs]
  (reduce
    (fn [acc x]
      (cond
        (or (nil? acc) (list? acc)) (cons x acc)
        (vector? acc) (list->vector (concat (to-list acc) (list x)))
        (and (set? acc) (sorted? acc)) (sorted-set-put acc x)
        (set? acc) (list->set (cons x (to-list acc)))
        (map? acc) (assoc acc (first x) (first (rest x)))
        true (throw :invalid-conj-target (list :coll acc))))
    coll
    xs))

contains?

fn -- (contains? coll k)

True if coll has an entry for key/index k -- a map/sorted-map key, a vector index (bounds-checked), or set/sorted-set membership. nil never contains anything.

Example:

(contains? [1 2 3] 1)
;;=> true

Source:

(defn contains?
  [coll k]
  (not (= (get coll k not-found-sentinel) not-found-sentinel)))

count

fn -- (count coll)

The number of elements in coll.

Example:

(count (list 1 2 3))
;;=> 3

Source:

(defn count
  [coll]
  (count-onto (to-list coll) 0))

count-onto

fn -- (count-onto items n)

Accumulates a running count of items onto n -- count's own worker, tail-recursive (unlike a direct (+ 1 (count (rest items))) body, which would wrap its own recursive call and so never benefit from Logos's TCO -- see reverse-onto's own accumulator pattern above, which this mirrors).

Example:

(count-onto (list 1 2 3) 0)
;;=> 3

Source:

(defn count-onto
  [items n]
  (cond
    (empty? items) n
    true (count-onto (rest items) (+ n 1))))

disj

fn -- (disj coll & xs)

Removes xs from set coll, one at a time. coll must be a set, sorted-set, or nil (a no-op).

Example:

(disj #{1 2 3} 2)
;;=> #{1 3}

Source:

(defn disj
  [coll & xs]
  (reduce
    (fn [acc x]
      (cond
        (nil? acc) nil
        (and (set? acc) (sorted? acc)) (sorted-set-remove acc x)
        (set? acc) (list->set (filter (fn [e] (not (= e x))) (to-list acc)))
        true (throw :invalid-disj-target (list :coll acc))))
    coll
    xs))

distinct

fn -- (distinct coll)

A new list of coll's elements with duplicates removed -- first occurrence kept, original order preserved.

Example:

(distinct (list 3 1 3 2 1))
;;=> (3 1 2)

Source:

(defn distinct
  [coll]
  (distinct-onto (to-list coll) ()))

distinct-onto

fn -- (distinct-onto items seen)

distinct's own worker: walks items, keeping each element the first time it's seen (checked against seen, accumulated in reverse), dropping every later duplicate.

Example:

(distinct-onto (list 1 1 2) ())
;;=> (1 2)

Source:

(defn distinct-onto
  [items seen]
  (cond
    (empty? items) (reverse seen)
    (some (fn [x] (= x (first items))) seen) (distinct-onto (rest items) seen)
    true (distinct-onto (rest items) (cons (first items) seen))))

drop

fn -- (drop n coll)

A list of coll with its first n elements removed (or (), if coll has fewer than n).

Example:

(drop 2 (list 1 2 3 4))
;;=> (3 4)

Source:

(defn drop
  [n coll]
  (let [items (to-list coll)]
    (cond
      (<= n 0) items
      (empty? items) ()
      true (drop (- n 1) (rest items)))))

drop-while

fn -- (drop-while pred coll)

coll with its leading elements for which (pred x) is truthy removed, starting from the first one that isn't.

Example:

(drop-while pos? (list 1 2 -1 3))
;;=> (-1 3)

Source:

(defn drop-while
  [pred coll]
  (let [items (to-list coll)]
    (cond
      (empty? items) ()
      (pred (first items)) (drop-while pred (rest items))
      true items)))

empty?

fn -- (empty? coll)

True if coll is empty -- nil, (), [], {}, and #{} all count.

Example:

(empty? [])
;;=> true

Source:

(defn empty?
  [coll]
  (= (to-list coll) ()))

every?

fn -- (every? pred coll)

True if (pred x) is truthy for every element of coll (vacuously true for an empty coll).

Example:

(every? pos? (list 1 2 3))
;;=> true

Source:

(defn every?
  [pred coll]
  (let [items (to-list coll)]
    (cond
      (empty? items) true
      (pred (first items)) (every? pred (rest items))
      true false)))

filter

fn -- (filter pred coll)

A new list of only coll's elements for which (pred element) is truthy, in order.

Example:

(filter even? (list 1 2 3 4))
;;=> (2 4)

Source:

(defn filter
  [pred coll]
  (filter-onto pred (to-list coll) ()))

filter-onto

fn -- (filter-onto pred items acc)

filter's own worker -- tail-recursive, same pattern.

Example:

(filter-onto even? (list 1 2 3 4) ())
;;=> (2 4)

Source:

(defn filter-onto
  [pred items acc]
  (cond
    (empty? items) (reverse acc)
    (pred (first items)) (filter-onto pred (rest items) (cons (first items) acc))
    true (filter-onto pred (rest items) acc)))

flatten

fn -- (flatten coll)

A single, flat list of every non-sequential leaf in coll, descending into nested lists/vectors only -- not maps/sets/strings, matching real Clojure's own sequential?-based descent. (flatten x) for a non-sequential top-level x is (), also matching Clojure.

Example:

(flatten [1 [2 3] 4])
;;=> (1 2 3 4)

Source:

(defn flatten
  [coll]
  (if (or (list? coll) (vector? coll)) (reverse (flatten-onto coll ())) ()))

flatten-onto

fn -- (flatten-onto coll acc)

Accumulates every non-sequential leaf reachable from coll onto acc, in reverse order -- flatten's own worker. Public despite being an implementation detail; see this file's header comment.

Example:

(flatten-onto (list 1 (list 2 3)) ())
;;=> (3 2 1)

Source:

(defn flatten-onto
  [coll acc]
  (if (or (list? coll) (vector? coll))
    (reduce (fn [acc2 x] (flatten-onto x acc2)) acc (to-list coll))
    (cons coll acc)))

frequencies

fn -- (frequencies coll)

A map of each distinct element of coll to the number of times it appears.

Example:

(frequencies (list 1 1 2))
;;=> {1 2 2 1}

Source:

(defn frequencies
  [coll]
  (reduce (fn [acc x] (assoc acc x (inc (get acc x 0)))) {} (to-list coll)))

get-in

fn -- (get-in coll ks) / (get-in coll ks not-found)

Nested get: walks ks (a list/vector of keys/indices) into coll, returning not-found (default nil) if any step along the way is missing.

Example:

(get-in {:a {:b 1}} [:a :b])
;;=> 1

Source:

(defn get-in
  ([coll ks] (get-in coll ks nil))
  ([coll ks not-found]
    (let [result (get-in-walk coll (to-list ks))]
      (if (= result get-in-miss) not-found result))))

get-in-miss

var

Internal-only marker get-in-walk uses to detect a missing intermediate step without confusing it with a caller-supplied not-found value that might otherwise collide with a real one. Public despite being an implementation detail -- see not-found-sentinel's own comment above for why.

Example:

get-in-miss
;;=> :logos.core/get-in-miss

Source:

(def get-in-miss
  (keyword "logos.core" "get-in-miss"))

get-in-walk

fn -- (get-in-walk coll ks)

get-in's own worker -- walks ks into coll, short-circuiting to get-in-miss the moment any step along the way is missing.

Example:

(get-in-walk {:a {:b 1}} (list :a :b))
;;=> 1

Source:

(defn get-in-walk
  [coll ks]
  (cond
    (empty? ks) coll
    true
    (let [v (get coll (first ks) get-in-miss)]
      (if (= v get-in-miss) get-in-miss (get-in-walk v (rest ks))))))

group-by

fn -- (group-by f coll)

A map of (f x) to a vector of every x in coll for which f produced that key, in original order -- real Clojure semantics exactly, including the vector-shaped groups.

Example:

(group-by even? (list 1 2 3 4))
;;=> {false [1 3] true [2 4]}

Source:

(defn group-by
  [f coll]
  (reduce (fn [acc x] (assoc acc (f x) (conj (get acc (f x) []) x))) {} (to-list coll)))

interleave

fn -- (interleave & colls)

Interleaves elements from each of colls, stopping at the shortest: (interleave [1 2] [:a :b]) => (1 :a 2 :b). (interleave) is ().

Example:

(interleave [1 2] [:a :b])
;;=> (1 :a 2 :b)

Source:

(defn interleave
  [& colls]
  (if (empty? colls) () (interleave-onto (map to-list colls) ())))

interleave-onto

fn -- (interleave-onto colls acc)

Accumulates one round-robin pass across colls onto acc, in reverse order, stopping as soon as any one of colls runs out -- interleave's own worker. Public despite being an implementation detail; see this file's header comment.

Example:

(interleave-onto (list (list 1 2) (list :a :b)) ())
;;=> (1 :a 2 :b)

Source:

(defn interleave-onto
  [colls acc]
  (if (some empty? colls)
    (reverse acc)
    (interleave-onto (map rest colls) (reduce (fn [a c] (cons (first c) a)) acc colls))))

interpose

fn -- (interpose sep coll)

A new list with sep inserted between every pair of coll's elements.

Example:

(interpose :x (list 1 2 3))
;;=> (1 :x 2 :x 3)

Source:

(defn interpose
  [sep coll]
  (interpose-onto sep (to-list coll) ()))

interpose-onto

fn -- (interpose-onto sep items acc)

Accumulates items onto acc in reverse order, with sep inserted between every pair -- interpose's own worker. Public despite being an implementation detail; see this file's header comment.

Example:

(interpose-onto :x (list 1 2 3) ())
;;=> (1 :x 2 :x 3)

Source:

(defn interpose-onto
  [sep items acc]
  (cond
    (empty? items) (reverse acc)
    (empty? (rest items)) (reverse (cons (first items) acc))
    true (interpose-onto sep (rest items) (cons sep (cons (first items) acc)))))

into

fn -- (into to from)

Pours every element of from into to, in to's own collection shape. from may be a list, vector, map, or set (or nil); to must be a list, vector, map, set, or nil (treated as ()).

Example:

(into [] (list 1 2 3))
;;=> [1 2 3]

Source:

(defn into
  [to from]
  (cond
    (or (nil? to) (list? to)) (reduce (fn [acc x] (cons x acc)) to (to-list from))
    (vector? to) (list->vector (concat (to-list to) (to-list from)))
    ;; `reduce conj`, not a `list->set (concat ...)` rebuild -- the
    ;; latter would silently demote a sorted-set `to` into a plain set,
    ;; losing both its order and comparator. `conj` (above) is already
    ;; sorted-set-aware, so reusing it here keeps this branch correct
    ;; for both shapes with no separate sorted-set-specific logic.
    (set? to) (reduce conj to (to-list from))
    (map? to)
    (reduce (fn [acc pair] (assoc acc (first pair) (first (rest pair)))) to (to-list from))
    true (throw :invalid-into-target (list :to to))))

keys

fn -- (keys coll)

A list of coll's keys, in coll's own iteration order. coll must be a map or sorted-map (or nil, treated as empty).

Example:

(keys {:a 1 :b 2})
;;=> (:a :b)

Source:

(defn keys
  [coll]
  (if (or (nil? coll) (map? coll))
    (map first (to-list coll))
    (throw :invalid-args (list :keys coll))))

last

fn -- (last coll)

The last element of coll, or nil if it's empty.

Example:

(last (list 1 2 3))
;;=> 3

Source:

(defn last
  [coll]
  (let [items (to-list coll)]
    (cond
      (empty? items) nil
      (empty? (rest items)) (first items)
      true (last (rest items)))))

map

fn -- (map f coll)

A new list with f applied to every element of coll, in order.

Example:

(map inc (list 1 2 3))
;;=> (2 3 4)

Source:

(defn map
  [f coll]
  (map-onto f (to-list coll) ()))

map-onto

fn -- (map-onto f items acc)

map's own worker -- tail-recursive, same accumulate-then-reverse pattern as take-onto/count-onto above.

Example:

(map-onto inc (list 1 2 3) ())
;;=> (2 3 4)

Source:

(defn map-onto
  [f items acc]
  (cond
    (empty? items) (reverse acc)
    true (map-onto f (rest items) (cons (f (first items)) acc))))

mapcat

fn -- (mapcat f coll)

Maps f over coll, then concatenates every result into one flat list -- f must return something concat-able (a list, vector, or nil) per element.

Example:

(mapcat (fn [x] (list x x)) (list 1 2))
;;=> (1 1 2 2)

Source:

(defn mapcat
  [f coll]
  (apply concat (map f coll)))

merge

fn -- (merge & maps)

Merges maps left to right -- a key present in more than one wins from the LAST map that has it. (merge) is nil; nil maps are skipped.

Example:

(merge {:a 1} {:b 2})
;;=> {:a 1 :b 2}

Source:

(defn merge
  [& maps]
  (reduce
    (fn [acc m]
      (cond
        (nil? m) acc
        (nil? acc) m
        true (into acc (to-list m))))
    nil
    maps))

merge-with

fn -- (merge-with f & maps)

Like merge, but a key present in more than one map is resolved via (f old-val new-val) instead of the later map unconditionally winning.

Example:

(merge-with + {:a 1} {:a 2})
;;=> {:a 3}

Source:

(defn merge-with
  [f & maps]
  (reduce
    (fn [acc m]
      (cond
        (nil? m) acc
        (nil? acc) m
        true
        (reduce
          (fn [acc2 pair]
            (let [k (first pair) v (first (rest pair))]
              (if (contains? acc2 k) (assoc acc2 k (f (get acc2 k) v)) (assoc acc2 k v))))
          acc
          (to-list m))))
    nil
    maps))

not-found-sentinel

var

Internal-only marker contains?/get-in use to tell 'genuinely absent' apart from 'present with value nil' -- never meant to be seen by calling code, hence the deliberately-unlikely-to-collide name.

Example:

not-found-sentinel
;;=> :logos.core/not-found

Source:

(def not-found-sentinel
  (keyword "logos.core" "not-found"))

nth

fn -- (nth coll n) / (nth coll n not-found)

The element of coll at index n (0-based). 2-arity throws :index-out-of-bounds if n is out of range; 3-arity returns not-found instead.

Example:

(nth (list 10 20 30) 1)
;;=> 20

Source:

(defn nth
  ([coll n]
    (let [items (to-list coll)]
      (if (or (< n 0) (>= n (count items))) (throw :index-out-of-bounds n) (first (drop n items)))))
  ([coll n not-found]
    (let [items (to-list coll)]
      (if (or (< n 0) (>= n (count items))) not-found (first (drop n items))))))

partition

fn -- (partition n coll) / (partition n step coll)

Chunks coll into vectors of n elements, non-overlapping by default (or stepping by step if given -- less than n for overlapping chunks, more to skip elements); a trailing chunk shorter than n is dropped.

Example:

(partition 2 (list 1 2 3 4))
;;=> ([1 2] [3 4])

Source:

(defn partition
  ([n coll] (partition n n coll))
  ([n step coll]
    (if (or (<= n 0) (<= step 0))
      (throw :invalid-partition-size (list :n n :step step))
      (partition-onto n step (to-list coll) ()))))

partition-all

fn -- (partition-all n coll) / (partition-all n step coll)

Like partition, but keeps a trailing chunk shorter than n instead of dropping it.

Example:

(partition-all 2 (list 1 2 3))
;;=> ([1 2] [3])

Source:

(defn partition-all
  ([n coll] (partition-all n n coll))
  ([n step coll]
    (if (or (<= n 0) (<= step 0))
      (throw :invalid-partition-size (list :n n :step step))
      (partition-all-onto n step (to-list coll) ()))))

partition-all-onto

fn -- (partition-all-onto n step items acc)

Accumulates items chunked into vectors of n, stepping by step, onto acc in reverse order, keeping a short trailing chunk -- partition-all's own worker. Public despite being an implementation detail; see this file's header comment.

Example:

(partition-all-onto 2 2 (list 1 2 3) ())
;;=> ([1 2] [3])

Source:

(defn partition-all-onto
  [n step items acc]
  (cond
    (empty? items) (reverse acc)
    true (partition-all-onto n step (drop step items) (cons (list->vector (take n items)) acc))))

partition-by

fn -- (partition-by f coll)

Chunks coll into vectors of consecutive elements that share the same (f x), in order.

Example:

(partition-by even? (list 1 3 2 4))
;;=> ([1 3] [2 4])

Source:

(defn partition-by
  [f coll]
  (partition-by-onto f (to-list coll) nil nil ()))

partition-by-onto

fn -- (partition-by-onto f items current-key current-group acc)

Accumulates items chunked by consecutive elements sharing (f x) onto acc in reverse order, tracking the in-progress chunk's own key (current-key) and elements (current-group) -- partition-by's own worker. Public despite being an implementation detail; see this file's header comment.

Example:

(partition-by-onto even? (list 1 3 2 4) nil nil ())
;;=> ([1 3] [2 4])

Source:

(defn partition-by-onto
  [f items current-key current-group acc]
  (cond
    (empty? items)
    (if (nil? current-group)
      (reverse acc)
      (reverse (cons (list->vector (reverse current-group)) acc)))
    true
    (let [x (first items) k (f x)]
      (cond
        (nil? current-group) (partition-by-onto f (rest items) k (list x) acc)
        (= k current-key) (partition-by-onto f (rest items) current-key (cons x current-group) acc)
        true
        (partition-by-onto f (rest items) k (list x)
          (cons (list->vector (reverse current-group)) acc))))))

partition-onto

fn -- (partition-onto n step items acc)

Accumulates items chunked into vectors of n, stepping by step, onto acc in reverse order, dropping a short trailing chunk -- partition's own worker. Public despite being an implementation detail; see this file's header comment.

Example:

(partition-onto 2 2 (list 1 2 3 4) ())
;;=> ([1 2] [3 4])

Source:

(defn partition-onto
  [n step items acc]
  (if (< (count items) n)
    (reverse acc)
    (partition-onto n step (drop step items) (cons (list->vector (take n items)) acc))))

peek

fn -- (peek coll)

The 'top' of coll's stack shape: the first element for a list, the last for a vector (Clojure's own two different "natural end" conventions for the two shapes). nil for an empty collection.

Example:

(peek [1 2 3])
;;=> 3

Source:

(defn peek
  [coll]
  (cond
    (vector? coll) (last (to-list coll))
    true (first (to-list coll))))

pop

fn -- (pop coll)

coll with its 'top' removed (see peek): the rest for a list, everything but the last for a vector.

Example:

(pop [1 2 3])
;;=> [1 2]

Source:

(defn pop
  [coll]
  (cond
    (vector? coll) (list->vector (take (dec (count coll)) (to-list coll)))
    true (rest (to-list coll))))

range

fn -- (range end) / (range start end) / (range start end step)

A list of integers from start (default 0) up to (not including) end, stepping by step (default 1, may be negative). A 0 step throws :invalid-range-step rather than looping forever.

Example:

(range 5)
;;=> (0 1 2 3 4)

Source:

(defn range
  ([end] (range 0 end 1))
  ([start end] (range start end 1))
  ([start end step]
    (if (= step 0) (throw :invalid-range-step step) (range-onto start end step ()))))

range-onto

fn -- (range-onto start end step acc)

range's own worker -- tail-recursive, same accumulate-then-reverse pattern as take-onto/map-onto above.

Example:

(range-onto 0 5 1 ())
;;=> (0 1 2 3 4)

Source:

(defn range-onto
  [start end step acc]
  (cond
    (and (pos? step) (>= start end)) (reverse acc)
    (and (neg? step) (<= start end)) (reverse acc)
    true (range-onto (+ start step) end step (cons start acc))))

reduce

fn -- (reduce f coll) / (reduce f init coll)

Folds f (a 2-arg function) over coll left to right. 2-arity (reduce f coll) seeds from coll's first element (or calls (f) with no seed and no elements); 3-arity (reduce f init coll) always starts from the given init.

Example:

(reduce + (list 1 2 3 4))
;;=> 10

Source:

(def reduce
  (fn
    ([f coll]
      (let [items (to-list coll)]
        (cond
          (empty? items) (f)
          true (reduce f (first items) (rest items)))))
    ([f init coll]
      (let [items (to-list coll)]
        (cond
          (empty? items) init
          true (reduce f (f init (first items)) (rest items)))))))

repeat

fn -- (repeat n x)

A list of n copies of x. Unlike Clojure's own repeat, there is no unbounded 1-arity form -- that needs a real lazy sequence, which this eager seq layer doesn't have.

Example:

(repeat 3 :x)
;;=> (:x :x :x)

Source:

(defn repeat
  [n x]
  (repeat-onto n x ()))

repeat-onto

fn -- (repeat-onto n x acc)

repeat's own worker -- tail-recursive, same pattern.

Example:

(repeat-onto 3 :x ())
;;=> (:x :x :x)

Source:

(defn repeat-onto
  [n x acc]
  (cond
    (<= n 0) (reverse acc)
    true (repeat-onto (- n 1) x (cons x acc))))

reverse

fn -- (reverse coll)

A new list with coll's elements in reverse order.

Example:

(reverse (list 1 2 3))
;;=> (3 2 1)

Source:

(defn reverse
  [coll]
  (reverse-onto coll ()))

reverse-onto

fn -- (reverse-onto coll acc)

Accumulates coll onto acc in reverse order -- reverse's own worker. Public despite being an implementation detail; see this file's header comment.

Example:

(reverse-onto (list 1 2 3) ())
;;=> (3 2 1)

Source:

(defn reverse-onto
  [coll acc]
  (let [items (to-list coll)]
    (cond
      (empty? items) acc
      true (reverse-onto (rest items) (cons (first items) acc)))))

second

fn -- (second coll)

The second element of coll, or nil if it has fewer than two.

Example:

(second (list 1 2 3))
;;=> 2

Source:

(defn second
  [coll]
  (nth coll 1 nil))

select-keys

fn -- (select-keys coll ks)

A new map containing only coll's entries whose key is in ks. Always returns a plain map even if coll was sorted -- a real, minor divergence from Clojure (which preserves a sorted-map's own shape here too), not worth a dedicated sorted-preserving path for this one function.

Example:

(select-keys {:a 1 :b 2 :c 3} [:a :c])
;;=> {:a 1 :c 3}

Source:

(defn select-keys
  [coll ks]
  (reduce (fn [acc k] (if (contains? coll k) (assoc acc k (get coll k)) acc)) {} (to-list ks)))

some

fn -- (some pred coll)

The first truthy (pred x) result over coll's elements, or nil if none are truthy -- returns pred's own return value (which may not be x itself), matching real Clojure, not just whether one existed.

Example:

(some even? (list 1 3 4))
;;=> true

Source:

(defn some
  [pred coll]
  (let [items (to-list coll)]
    (cond
      (empty? items) nil
      true
      (let [result (pred (first items))] (if result result (some pred (rest items)))))))

sort

fn -- (sort coll)

A new list of coll's elements in ascending order, per compare.

Example:

(sort (list 3 1 2))
;;=> (1 2 3)

Source:

(defn sort
  [coll]
  (reduce (fn [acc x] (sort-insert x acc)) () (to-list coll)))

sort-by

fn -- (sort-by keyfn coll)

Like sort, but compares (keyfn x) for each element instead of x itself.

Example:

(sort-by (fn [x] (- x)) (list 1 3 2))
;;=> (3 2 1)

Source:

(defn sort-by
  [keyfn coll]
  (reduce (fn [acc x] (sort-by-insert keyfn x acc)) () (to-list coll)))

sort-by-insert

fn -- (sort-by-insert keyfn x sorted)

sort-insert's sort-by counterpart -- compares (keyfn x) instead of x itself.

Example:

(sort-by-insert identity 2 (list 1 3))
;;=> (1 2 3)

Source:

(defn sort-by-insert
  [keyfn x sorted]
  (cond
    (empty? sorted) (list x)
    (<= (compare (keyfn x) (keyfn (first sorted))) 0) (cons x sorted)
    true (cons (first sorted) (sort-by-insert keyfn x (rest sorted)))))

sort-insert

fn -- (sort-insert x sorted)

Inserts x into already-sorted list sorted, keeping it sorted -- sort's own worker.

Example:

(sort-insert 2 (list 1 3))
;;=> (1 2 3)

Source:

(defn sort-insert
  [x sorted]
  (cond
    (empty? sorted) (list x)
    (<= (compare x (first sorted)) 0) (cons x sorted)
    true (cons (first sorted) (sort-insert x (rest sorted)))))

take

fn -- (take n coll)

A list of the first n elements of coll (or all of them, if coll has fewer than n).

Example:

(take 2 (list 1 2 3))
;;=> (1 2)

Source:

(defn take
  [n coll]
  (take-onto n (to-list coll) ()))

take-onto

fn -- (take-onto n items acc)

take's own worker -- tail-recursive, same accumulate-then-reverse pattern as reverse-onto/count-onto above (a direct (cons (first items) (take ...)) body would wrap its own recursive call, losing TCO).

Example:

(take-onto 2 (list 1 2 3) ())
;;=> (1 2)

Source:

(defn take-onto
  [n items acc]
  (cond
    (<= n 0) (reverse acc)
    (empty? items) (reverse acc)
    true (take-onto (- n 1) (rest items) (cons (first items) acc))))

take-while

fn -- (take-while pred coll)

A list of coll's leading elements for which (pred x) is truthy, stopping at the first one that isn't.

Example:

(take-while pos? (list 1 2 -1 3))
;;=> (1 2)

Source:

(defn take-while
  [pred coll]
  (take-while-onto pred (to-list coll) ()))

take-while-onto

fn -- (take-while-onto pred items acc)

take-while's own worker -- tail-recursive, same accumulate-then- reverse pattern as take-onto/map-onto etc. above.

Example:

(take-while-onto pos? (list 1 2 -1 3) ())
;;=> (1 2)

Source:

(defn take-while-onto
  [pred items acc]
  (cond
    (empty? items) (reverse acc)
    (pred (first items)) (take-while-onto pred (rest items) (cons (first items) acc))
    true (reverse acc)))

update

fn -- (update coll k f & args)

Returns coll with the value at k replaced by (f (get coll k) & args).

Example:

(update {:a 1} :a inc)
;;=> {:a 2}

Source:

(defn update
  [coll k f & args]
  (assoc coll k (apply f (get coll k) args)))

update-in

fn -- (update-in coll ks f & args)

Nested update: (update-in {:a {:b 1}} [:a :b] inc) => {:a {:b 2}}.

Example:

(update-in {:a {:b 1}} [:a :b] inc)
;;=> {:a {:b 2}}

Source:

(defn update-in
  [coll ks f & args]
  (let [ks-list (to-list ks)]
    (cond
      (empty? ks-list) (apply f coll args)
      (empty? (rest ks-list))
      (assoc coll (first ks-list) (apply f (get coll (first ks-list)) args))
      true
      (assoc coll (first ks-list)
        (apply update-in (get coll (first ks-list)) (rest ks-list) f args)))))

vals

fn -- (vals coll)

A list of coll's values, in coll's own iteration order. coll must be a map or sorted-map (or nil, treated as empty).

Example:

(vals {:a 1 :b 2})
;;=> (1 2)

Source:

(defn vals
  [coll]
  (if (or (nil? coll) (map? coll))
    (map (fn [pair] (first (rest pair))) (to-list coll))
    (throw :invalid-args (list :vals coll))))

zipmap

fn -- (zipmap ks vs)

A map pairing each of ks with the positionally-corresponding element of vs, stopping at the shorter of the two.

Example:

(zipmap (list :a :b) (list 1 2))
;;=> {:a 1 :b 2}

Source:

(defn zipmap
  [ks vs]
  (zipmap-onto (to-list ks) (to-list vs) {}))

zipmap-onto

fn -- (zipmap-onto ks vs acc)

Accumulates ks/vs pairs onto map acc, stopping at the shorter of the two -- zipmap's own worker. Public despite being an implementation detail; see this file's header comment.

Example:

(zipmap-onto (list :a :b) (list 1 2) {})
;;=> {:a 1 :b 2}

Source:

(defn zipmap-onto
  [ks vs acc]
  (cond
    (or (empty? ks) (empty? vs)) acc
    true (zipmap-onto (rest ks) (rest vs) (assoc acc (first ks) (first vs)))))