Location: src/hql/lib/stdlib/js/stdlib.js
HQL's standard library provides functional programming utilities for working with collections, sequences, and data transformations. All functions are lazy by default and support both arrays and lazy sequences.
first(coll)Returns the first element of a collection.
(first [1 2 3]) // → 1
(first "hello") // → "h"
(first []) // → undefined
rest(coll)Returns all but the first element as a lazy sequence.
(rest [1 2 3]) // → (2 3)
(rest [1]) // → ()
(rest []) // → ()
Lazy: Yes
cons(item, coll)Prepends an item to a collection, returning a lazy sequence.
(cons 1 [2 3]) // → (1 2 3)
(cons 0 []) // → (0)
Lazy: Yes
take(n, coll)Takes the first n elements from a collection as a lazy sequence.
(take 3 [1 2 3 4 5]) // → (1 2 3)
(take 10 [1 2]) // → (1 2)
(take 0 [1 2]) // → ()
Lazy: Yes
drop(n, coll)Drops the first n elements from a collection, returning lazy sequence.
(drop 2 [1 2 3 4 5]) // → (3 4 5)
(drop 10 [1 2]) // → ()
Lazy: Yes
concat(...colls)Concatenates multiple collections into a lazy sequence.
(concat [1 2] [3 4]) // → (1 2 3 4)
(concat [] [1]) // → (1)
(concat [1] [] [2]) // → (1 2)
Lazy: Yes
flatten(coll)Flattens nested collections one level deep.
(flatten [[1 2] [3 4]]) // → (1 2 3 4)
(flatten [1 [2 3] 4]) // → (1 2 3 4)
(flatten [[[1]] [2]]) // → ([1] 2) // only one level
Lazy: Yes
distinct(coll)Returns lazy sequence of unique elements (preserves first occurrence).
(distinct [1 2 2 3 1]) // → (1 2 3)
(distinct "hello") // → ("h" "e" "l" "o")
Lazy: Yes
range([start,] end [, step])Generates a lazy sequence of numbers.
(range 5) // → (0 1 2 3 4)
(range 2 5) // → (2 3 4)
(range 0 10 2) // → (0 2 4 6 8)
Lazy: Yes
map(fn, coll)Applies function to each element, returning lazy sequence.
(map (fn [x] (* x 2)) [1 2 3]) // → (2 4 6)
(map str [1 2 3]) // → ("1" "2" "3")
Lazy: Yes
filter(pred, coll)Returns lazy sequence of elements satisfying predicate.
(filter isEven [1 2 3 4]) // → (2 4)
(filter (fn [x] (> x 5)) [3 6 9]) // → (6 9)
Lazy: Yes
reduce(fn, init, coll)Reduces collection to single value.
(reduce + 0 [1 2 3 4]) // → 10
(reduce * 1 [1 2 3 4]) // → 24
Lazy: No (must realize entire collection)
mapIndexed(fn, coll)Maps function receiving (index, item) over collection.
(mapIndexed (fn [i x] [i x]) ["a" "b" "c"])
// → ([0 "a"] [1 "b"] [2 "c"])
(mapIndexed (fn [i x] (* i x)) [10 20 30])
// → (0 20 60)
Lazy: Yes
keepIndexed(fn, coll)Like mapIndexed but filters nil results.
(keepIndexed (fn [i x] (if (isEven i) x nil)) ["a" "b" "c" "d"])
// → ("a" "c")
Lazy: Yes
mapcat(fn, coll)Maps function then concatenates results (flat-map).
(mapcat (fn [x] [x x]) [1 2 3]) // → (1 1 2 2 3 3)
(mapcat rest [[1 2 3] [4 5] [6]]) // → (2 3 5)
Lazy: Yes
keep(fn, coll)Maps function and filters nil results.
(keep (fn [x] (if (> x 0) x nil)) [-1 0 1 2])
// → (1 2)
Lazy: Yes
seq(coll)Returns a sequence view of the collection, or nil if empty.
(seq [1 2 3]) // → (1 2 3)
(seq []) // → nil
(seq "hello") // → ("h" "e" "l" "l" "o")
empty(coll)Returns an empty collection of the same type.
(empty [1 2 3]) // → []
(empty #[1 2 3]) // → #[]
conj(coll, item)Adds item to collection in type-appropriate position.
(conj [1 2] 3) // → [1 2 3]
(conj #[1 2] 3) // → #[1 2 3]
(conj '(1 2) 0) // → (0 1 2)
into(to, from)Adds all elements from from into to.
(into [] [1 2 3]) // → [1 2 3]
(into #[] [1 2 2 3]) // → #[1 2 3]
(into {} [["a" 1] ["b" 2]]) // → {a: 1, b: 2}
isEmpty(coll)Returns true if collection is empty.
(isEmpty []) // → true
(isEmpty [1]) // → false
(isEmpty nil) // → true
some(pred, coll)Returns first truthy value of (pred item), or nil.
(some isEven [1 3 5]) // → nil
(some isEven [1 2 3]) // → 2 (first matching item)
(some (fn [x] (> x 5)) [1 3 6 9]) // → 6
every(pred, coll)Returns true if predicate returns truthy for all elements.
(every isEven [2 4 6]) // → true
(every isEven [2 3 4]) // → false
(every isPositive []) // → true (vacuous truth)
notAny(pred, coll)Returns true if predicate returns false for all elements.
(notAny isEven [1 3 5]) // → true
(notAny isEven [1 2 3]) // → false
notEvery(pred, coll)Returns true if predicate returns false for at least one element.
(notEvery isEven [2 4 6]) // → false
(notEvery isEven [2 3 4]) // → true
isSome(x)Returns true if x is not nil (null or undefined).
(isSome 0) // → true
(isSome false) // → true
(isSome nil) // → false
(isSome undefined) // → false
doall(coll)Forces realization of lazy sequence, returning array.
(doall (take 3 [1 2 3 4])) // → [1 2 3]
(doall (map inc [1 2 3])) // → [2 3 4]
Use: When you need an actual array instead of lazy sequence
realized(seq)Checks if a sequence has been realized.
(var lazySeq (take 5 [1 2 3 4 5]))
(realized lazySeq) // → false
(doall lazySeq)
(realized lazySeq) // → true
comp(...fns)Composes functions right-to-left.
(var addThenDouble (comp (fn [x] (* x 2)) (fn [x] (+ x 1))))
(addThenDouble 5) // → 12 // (5 + 1) * 2
partial(fn, ...args)Partially applies arguments to a function.
(var add10 (partial + 10))
(add10 5) // → 15
(add10 20) // → 30
apply(fn, args)Applies function to array of arguments.
(apply + [1 2 3 4]) // → 10
(apply max [5 2 9 1]) // → 9
get(map, key [, notFound])Gets value from map by key.
(get {a: 1, b: 2} "a") // → 1
(get {a: 1} "b") // → undefined
(get {a: 1} "b" "default") // → "default"
getIn(map, path [, notFound])Gets value at nested path (array of keys).
(getIn {a: {b: {c: 1}}} ["a" "b" "c"]) // → 1
(getIn {a: {b: 1}} ["a" "x"] "n/a") // → "n/a"
assoc(map, key, value)Associates key with value in map, returning new map.
(assoc {a: 1} "b" 2) // → {a: 1, b: 2}
(assoc {} "x" 10) // → {x: 10}
Immutable: Returns new map
assocIn(map, path, value)Associates value at nested path.
(assocIn {} ["a" "b" "c"] 1) // → {a: {b: {c: 1}}}
(assocIn {a: {b: 1}} ["a" "c"] 2) // → {a: {b: 1, c: 2}}
Immutable: Returns new map
dissoc(map, key)Removes key from map, returning new map.
(dissoc {a: 1, b: 2} "b") // → {a: 1}
Immutable: Returns new map
update(map, key, fn)Updates value at key by applying function.
(update {a: 1} "a" inc) // → {a: 2}
(update {a: 1} "a" (fn [x] (* x 10))) // → {a: 10}
Immutable: Returns new map
updateIn(map, path, fn)Updates value at nested path by applying function.
(updateIn {a: {b: 1}} ["a" "b"] inc) // → {a: {b: 2}}
Immutable: Returns new map
merge(...maps)Merges multiple maps, later values override.
(merge {a: 1} {b: 2}) // → {a: 1, b: 2}
(merge {a: 1} {a: 2}) // → {a: 2}
Immutable: Returns new map
keys(map)Returns all keys from map.
(keys {a: 1, b: 2}) // → ["a", "b"]
groupBy(fn, coll)Groups collection by result of function.
(groupBy (fn [x] (% x 2)) [1 2 3 4 5])
// → {0: [2, 4], 1: [1, 3, 5]}
(groupBy .length ["a" "bb" "ccc" "dd"])
// → {1: ["a"], 2: ["bb", "dd"], 3: ["ccc"]}
iterate(fn, initial)Generates infinite lazy sequence by repeatedly applying function.
(take 5 (iterate (fn [x] (+ x 1)) 0)) // → (0 1 2 3 4)
(take 4 (iterate (fn [x] (* x 2)) 1)) // → (1 2 4 8)
Lazy: Yes (infinite sequence!)
repeat(x)Returns infinite lazy sequence of the same value.
(take 5 (repeat "hello")) // → ("hello" "hello" "hello" "hello" "hello")
(take 3 (repeat 42)) // → (42 42 42)
Lazy: Yes (infinite sequence!)
repeatedly(fn)Returns infinite lazy sequence calling function each time.
(take 3 (repeatedly (fn [] (Math.random)))) // → (0.123 0.456 0.789)
(take 4 (repeatedly (fn [] (Date.now)))) // → timestamps
Lazy: Yes (infinite sequence!)
cycle(coll)Returns infinite lazy sequence cycling through collection.
(take 7 (cycle [1 2 3])) // → (1 2 3 1 2 3 1)
(take 5 (cycle "ab")) // → ("a" "b" "a" "b" "a")
Lazy: Yes (infinite sequence!)
count(coll)Returns count of elements in collection.
(count [1 2 3]) // → 3
(count "hello") // → 5
(count []) // → 0
Note: Forces realization of lazy sequences
nth(coll, n [, notFound])Returns element at index n.
(nth [1 2 3] 1) // → 2
(nth [1 2 3] 10) // → undefined
(nth [1 2 3] 10 "n/a") // → "n/a"
last(coll)Returns last element of collection.
(last [1 2 3]) // → 3
(last []) // → undefined
Note: Forces realization of lazy sequences
second(coll)Returns second element of collection.
(second [1 2 3]) // → 2
(second [1]) // → undefined
next(coll)Returns (seq (rest coll)), or nil if empty.
(next [1 2 3]) // → (2 3)
(next [1]) // → nil
(next []) // → nil
Note: Unlike rest which returns empty seq, next returns nil.
reverse(coll)Reverses a collection.
(reverse [1 2 3]) // → [3 2 1]
(reverse "hello") // → ["o" "l" "l" "e" "h"]
vec(coll)Converts collection to vector (array).
(vec (take 3 [1 2 3 4])) // → [1 2 3]
(vec "hello") // → ["h" "e" "l" "l" "o"]
Same as: doall
set(coll)Converts collection to set (unique values).
(set [1 2 2 3 1]) // → Set{1, 2, 3}
str(x) - Convert to stringint(x) - Convert to integerfloat(x) - Convert to floatbool(x) - Convert to booleanvec(coll) - Convert to vector/arrayset(coll) - Convert to setlist(coll) - Convert to listMost stdlib functions return lazy sequences that are only realized when needed:
// This doesn't compute anything yet
(var lazyResult (map (fn [x] (* x 2)) (range 1000000)))
// This realizes only first 5 elements
(take 5 lazyResult) // Efficient!
Use doall or vec to force realization:
(doall (map inc [1 2 3])) // → [2 3 4] (array)
Some operations create infinite sequences - always limit them:
(take 10 (iterate inc 0)) // ✅ Safe
(doall (iterate inc 0)) // ❌ NEVER DO THIS - infinite loop!
Run stdlib tests:
deno task test:unit
All stdlib functions are:
See Also: