test(spec): collections contract (sequences, vectors, lists, maps, sets)

Add behavioral spec suites for the collection API (~180 cases). Writing them
surfaced and fixed real bugs:
- (count nil) errored; now 0 (Clojure semantics)
- (repeat x) and (repeatedly f) — the infinite 1-arg arities — were unsupported;
  now return lazy infinite seqs
- set equality used deep= (representation-sensitive), so a set of map literals
  could differ from an equal set built differently; now value-based (each
  element value-equal to some element of the other)

Known limitation filed: phm-typed maps (from hash-map) used as set elements /
map keys hash by identity (map *literals* are structs and work).

jpm test green.
This commit is contained in:
Yogthos 2026-06-05 00:08:37 -04:00
parent 16428179fa
commit b353d625f1
7 changed files with 303 additions and 15 deletions

View file

@ -12,6 +12,7 @@
{"_type":"issue","id":"jolt-40n","title":"HIGH: update/update-in/assoc-in fail on map literals (struct)","status":"closed","priority":2,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T18:09:56Z","created_by":"Yogthos","updated_at":"2026-06-04T18:40:42Z","closed_at":"2026-06-04T18:40:42Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"jolt-ytt","title":"HIGH: str semantics — (str nil)='nil' should be '', (str :b)='b' should be ':b'","status":"closed","priority":2,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T18:09:56Z","created_by":"Yogthos","updated_at":"2026-06-04T18:33:45Z","closed_at":"2026-06-04T18:33:45Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"jolt-9sb","title":"HIGH: destructuring gaps (nested seq, :strs, nested map, fn-param)","status":"closed","priority":2,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T18:09:55Z","created_by":"Yogthos","updated_at":"2026-06-04T18:31:24Z","closed_at":"2026-06-04T18:31:24Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"jolt-do7","title":"phm-typed maps as set elements / map keys hash by identity","description":"A map produced via hash-map/assoc (a Janet table/phm) used as a set element or map key hashes by identity, so #{{:a 1}} (struct elem) != #{(hash-map :a 1)} (phm elem) and such elements aren't retrievable by value. Map literals (structs) work. Needs value-based hashing for phm keys in PHM/PHS. Edge case; spec covers literal-map cases.","status":"open","priority":3,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-05T04:07:50Z","created_by":"Yogthos","updated_at":"2026-06-05T04:07:50Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"jolt-7dy","title":"MED: compiler path lacks IFn dispatch (collections-as-fn) — only interpreter fixed","status":"closed","priority":3,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T18:10:00Z","created_by":"Yogthos","updated_at":"2026-06-04T19:56:36Z","closed_at":"2026-06-04T19:56:36Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"jolt-90c","title":"MED: filter/take-while not lazy — infinite-seq (take N (filter p (range))) loops","status":"closed","priority":3,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T18:10:00Z","created_by":"Yogthos","updated_at":"2026-06-04T18:56:26Z","closed_at":"2026-06-04T18:56:26Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"jolt-7n5","title":"MED: REPL display — def/defn should print #'ns/name; lazy-seq printer realizes only head ((0 \u003cfunction\u003e))","status":"closed","priority":3,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T18:09:59Z","created_by":"Yogthos","updated_at":"2026-06-04T18:55:11Z","closed_at":"2026-06-04T18:55:11Z","dependency_count":0,"dependent_count":0,"comment_count":0}

View file

@ -201,7 +201,16 @@
(or sa sb) false
# sets
(or (set? a) (set? b))
(if (and (set? a) (set? b)) (deep= (phs-to-struct a) (phs-to-struct b)) false)
# value-based: same size and every element of a is value-equal to some
# element of b (so #{ {:a 1} } equals #{ (hash-map :a 1) } regardless of
# the elements' underlying representations)
(if (and (set? a) (set? b) (= (a :cnt) (b :cnt)))
(let [eb (phs-seq b)]
(var ok true)
(each x (phs-seq a)
(unless (some (fn [y] (jolt-equal? x y)) eb) (set ok false)))
ok)
false)
# maps: compare key/value pairs recursively, order-independent
true
(let [pa (eq-map-pairs a) pb (eq-map-pairs b)]
@ -388,6 +397,7 @@
(defn core-count [coll]
(cond
(nil? coll) 0
(core-sorted-map? coll) (length (keys (coll :map)))
(core-sorted-set? coll) (length (coll :items))
(lazy-seq? coll) (ls-count coll)
@ -1125,26 +1135,30 @@
(+= i step))
(tuple/slice (tuple ;result))))))
(def core-repeat (fn [n x]
(var result @[])
(var i 0)
(while (< i n)
(array/push result x)
(++ i))
result))
(defn core-repeat
"(repeat x) -> infinite lazy seq of x; (repeat n x) -> n copies of x."
[a & rest]
(if (= 0 (length rest))
(do (defn rstep [] (fn [] @[a (rstep)])) (make-lazy-seq (rstep)))
(let [n a x (in rest 0)]
(var result @[]) (var i 0)
(while (< i n) (array/push result x) (++ i))
result)))
(defn core-iterate [f x]
"Lazy infinite sequence x, (f x), (f (f x)), ..."
(defn istep [v] (fn [] @[v (istep (f v))]))
(make-lazy-seq (istep x)))
(defn core-repeatedly [n f]
(var result @[])
(var i 0)
(while (< i n)
(array/push result (f))
(++ i))
result)
(defn core-repeatedly
"(repeatedly f) -> infinite lazy seq of (f) calls; (repeatedly n f) -> n calls."
[a & rest]
(if (= 0 (length rest))
(do (defn rstep [] (fn [] @[(a) (rstep)])) (make-lazy-seq (rstep)))
(let [n a f (in rest 0)]
(var result @[]) (var i 0)
(while (< i n) (array/push result (f)) (++ i))
result)))
# ============================================================
# Higher-order functions

View file

@ -0,0 +1,28 @@
# Specification: lists (persistent singly-linked).
(use ../support/harness)
(defspec "list / construct & predicate"
["list" "[1 2 3]" "(list 1 2 3)"]
["empty list" "[]" "(list)"]
["quoted list" "[1 2 3]" "(quote (1 2 3))"]
["list? true" "true" "(list? (list 1 2))"]
["list? on conj result" "true" "(list? (conj (list 1) 0))"]
["count" "3" "(count (list 1 2 3))"]
["empty? true" "true" "(empty? (list))"]
["list = vector elts" "true" "(= (list 1 2 3) [1 2 3])"])
(defspec "list / access & update"
["first" "1" "(first (list 1 2 3))"]
["rest" "[2 3]" "(rest (list 1 2 3))"]
["peek is first" "1" "(peek (list 1 2 3))"]
["pop drops first" "[2 3]" "(pop (list 1 2 3))"]
["conj prepends" "[0 1 2]" "(conj (list 1 2) 0)"]
["conj many prepends" "[4 3 1 2]" "(conj (list 1 2) 3 4)"]
["cons prepends" "[0 1 2]" "(cons 0 (list 1 2))"]
["nth" "20" "(nth (list 10 20 30) 1)"])
(defspec "list / immutability & performance"
["conj does not mutate" "true" "(let [l (list 1 2 3) m (conj l 0)] (and (= l [1 2 3]) (= m [0 1 2 3])))"]
["reduce conj builds" "[2 1 0]" "(reduce conj (list) (range 3))"]
["O(1) conj at scale" "200000" "(count (reduce conj (list) (range 200000)))"]
["scale head correct" "199999" "(first (reduce conj (list) (range 200000)))"])

56
test/spec/maps-spec.janet Normal file
View file

@ -0,0 +1,56 @@
# Specification: maps (associative).
(use ../support/harness)
(defspec "map / construct & predicate"
["literal" "{:a 1}" "{:a 1}"]
["hash-map" "{:a 1, :b 2}" "(hash-map :a 1 :b 2)"]
["empty" "{}" "{}"]
["map? true" "true" "(map? {:a 1})"]
["map? false on vector" "false" "(map? [1 2])"]
["count" "2" "(count {:a 1 :b 2})"]
["empty? true" "true" "(empty? {})"]
["equality order-indep" "true" "(= {:a 1 :b 2} {:b 2 :a 1})"])
(defspec "map / access"
["get" "1" "(get {:a 1} :a)"]
["get missing nil" "nil" "(get {:a 1} :z)"]
["get default" ":x" "(get {:a 1} :z :x)"]
["keyword as fn" "1" "(:a {:a 1})"]
["keyword fn default" ":x" "(:z {:a 1} :x)"]
["map as fn" "1" "({:a 1} :a)"]
["get-in" "2" "(get-in {:a {:b 2}} [:a :b])"]
["get-in missing" "nil" "(get-in {:a {}} [:a :b])"]
["contains? key" "true" "(contains? {:a 1} :a)"]
["contains? missing" "false" "(contains? {:a 1} :z)"]
["find returns entry" "[:a 1]" "(find {:a 1} :a)"]
["keys" "true" "(= #{:a :b} (set (keys {:a 1 :b 2})))"]
["vals" "true" "(= #{1 2} (set (vals {:a 1 :b 2})))"])
(defspec "map / update"
["assoc adds" "{:a 1, :b 2}" "(assoc {:a 1} :b 2)"]
["assoc overwrites" "{:a 9}" "(assoc {:a 1} :a 9)"]
["assoc many" "{:a 1, :b 2}" "(assoc {} :a 1 :b 2)"]
["dissoc" "{:a 1}" "(dissoc {:a 1 :b 2} :b)"]
["dissoc many" "{:a 1}" "(dissoc {:a 1 :b 2 :c 3} :b :c)"]
["merge" "{:a 1, :b 2}" "(merge {:a 1} {:b 2})"]
["merge overwrites" "{:a 2}" "(merge {:a 1} {:a 2})"]
["merge-with" "{:a 3}" "(merge-with + {:a 1} {:a 2})"]
["update" "{:a 2}" "(update {:a 1} :a inc)"]
["update missing w/ fnil" "{:a 1}" "(update {} :a (fnil inc 0))"]
["update-in" "{:a {:b 2}}" "(update-in {:a {:b 1}} [:a :b] inc)"]
["assoc-in" "{:a {:b 1}}" "(assoc-in {} [:a :b] 1)"]
["select-keys" "{:a 1}" "(select-keys {:a 1 :b 2} [:a])"]
["into onto map" "{:a 1, :b 2}" "(into {:a 1} [[:b 2]])"]
["zipmap" "{:a 1, :b 2}" "(zipmap [:a :b] [1 2])"])
(defspec "map / iteration & entries"
["map over entries" "true" "(= #{1 2} (set (map val {:a 1 :b 2})))"]
["map keys" "true" "(= #{:a :b} (set (map key {:a 1 :b 2})))"]
["reduce over entries" "6" "(reduce (fn [a e] (+ a (val e))) 0 {:a 1 :b 2 :c 3})"]
["reduce-kv" "6" "(reduce-kv (fn [a k v] (+ a v)) 0 {:a 1 :b 2 :c 3})"]
["destructure entry" "true" "(= [[:a 2]] (into [] (map (fn [[k v]] [k (inc v)]) {:a 1})))"]
["first of map is entry" "true" "(let [e (first {:a 1})] (and (= (key e) :a) (= (val e) 1)))"]
["map-entry?" "true" "(map-entry? (first {:a 1}))"]
["count of nil map" "0" "(count nil)"]
["get from nil" "nil" "(get nil :a)"]
["immutability" "true" "(let [m {:a 1} n (assoc m :b 2)] (and (= m {:a 1}) (= n {:a 1 :b 2})))"])

View file

@ -0,0 +1,105 @@
# Specification: the sequence abstraction (clojure.core).
# Sequential expecteds use vector literals — Jolt's `=` treats vectors and lists
# with the same elements as equal, so [2 3 4] matches a (2 3 4) seq result.
(use ../support/harness)
(defspec "seq / access"
["first of vector" "1" "(first [1 2 3])"]
["first of list" "1" "(first (list 1 2 3))"]
["first of empty is nil" "nil" "(first [])"]
["first of nil is nil" "nil" "(first nil)"]
["second" "2" "(second [1 2 3])"]
["last" "3" "(last [1 2 3])"]
["rest of vector" "[2 3]" "(rest [1 2 3])"]
["rest of single" "[]" "(rest [1])"]
["rest of empty" "[]" "(rest [])"]
["next of single is nil" "nil" "(next [1])"]
["next of empty is nil" "nil" "(next [])"]
["nth" "30" "(nth [10 20 30] 2)"]
["nth with default" "99" "(nth [10] 5 99)"]
["nth out of range" :throws "(nth [10] 5)"]
["ffirst" "1" "(ffirst [[1 2] [3 4]])"]
["fnext" "2" "(fnext [1 2 3])"]
["nnext" "[3 4]" "(nnext [1 2 3 4])"])
(defspec "seq / construction"
["cons onto list" "[0 1 2]" "(cons 0 (list 1 2))"]
["cons onto vector" "[0 1 2]" "(cons 0 [1 2])"]
["cons onto nil" "[0]" "(cons 0 nil)"]
["conj vector appends" "[1 2 3]" "(conj [1 2] 3)"]
["conj list prepends" "[0 1 2]" "(conj (list 1 2) 0)"]
["conj multiple on vec" "[1 2 3 4]" "(conj [1 2] 3 4)"]
["conj multiple on list" "[4 3 1 2]" "(conj (list 1 2) 3 4)"]
["seq of empty is nil" "nil" "(seq [])"]
["seq of nil is nil" "nil" "(seq nil)"]
["seq of string" "[\\a \\b]" "(seq \"ab\")"]
["empty?" "true" "(empty? [])"]
["not empty?" "false" "(empty? [1])"]
["count" "3" "(count [1 2 3])"]
["count of nil" "0" "(count nil)"]
["count of string" "3" "(count \"abc\")"])
(defspec "seq / map filter reduce"
["map" "[2 3 4]" "(map inc [1 2 3])"]
["map two colls" "[5 7 9]" "(map + [1 2 3] [4 5 6])"]
["map stops at shortest" "[5 7]" "(map + [1 2] [4 5 6])"]
["map-indexed" "[[0 :a] [1 :b]]" "(map-indexed vector [:a :b])"]
["mapv" "[2 3 4]" "(mapv inc [1 2 3])"]
["filter" "[2 4]" "(filter even? [1 2 3 4])"]
["filterv" "[2 4]" "(filterv even? [1 2 3 4])"]
["remove" "[1 3]" "(remove even? [1 2 3 4])"]
["reduce" "10" "(reduce + [1 2 3 4])"]
["reduce with init" "20" "(reduce + 10 [1 2 3 4])"]
["reduce empty with init" "0" "(reduce + 0 [])"]
["reduce single no init" "5" "(reduce + [5])"]
["reduced short-circuits" "3" "(reduce (fn [a x] (if (> a 2) (reduced a) (+ a x))) 0 [1 2 3 4 5])"]
["reduce-kv" "6" "(reduce-kv (fn [a k v] (+ a v)) 0 {:a 1 :b 2 :c 3})"]
["reductions" "[1 3 6]" "(reductions + [1 2 3])"]
["mapcat" "[1 1 2 2]" "(mapcat (fn [x] [x x]) [1 2])"]
["keep" "[1 3]" "(keep (fn [x] (if (odd? x) x nil)) [1 2 3 4])"]
["some truthy" "true" "(some even? [1 2 3])"]
["some nil" "nil" "(some even? [1 3 5])"]
["every? true" "true" "(every? pos? [1 2 3])"]
["every? false" "false" "(every? pos? [1 -2 3])"])
(defspec "seq / take drop slice"
["take" "[1 2 3]" "(take 3 [1 2 3 4 5])"]
["take more than size" "[1 2]" "(take 5 [1 2])"]
["drop" "[4 5]" "(drop 3 [1 2 3 4 5])"]
["take-while" "[1 2]" "(take-while (fn [x] (< x 3)) [1 2 3 1])"]
["drop-while" "[3 1]" "(drop-while (fn [x] (< x 3)) [1 2 3 1])"]
["take-last" "[4 5]" "(take-last 2 [1 2 3 4 5])"]
["drop-last" "[1 2 3]" "(drop-last [1 2 3 4])"]
["take-nth" "[1 3 5]" "(take-nth 2 [1 2 3 4 5])"]
["partition" "[[1 2] [3 4]]" "(partition 2 [1 2 3 4 5])"]
["partition-all" "[[1 2] [3]]" "(partition-all 2 [1 2 3])"]
["split-at" "[[1 2] [3 4]]" "(split-at 2 [1 2 3 4])"])
(defspec "seq / transform"
["reverse" "[3 2 1]" "(reverse [1 2 3])"]
["sort" "[1 2 3]" "(sort [3 1 2])"]
["sort with comparator" "[3 2 1]" "(sort > [1 3 2])"]
["sort-by" "[[1] [2 2]]" "(sort-by count [[2 2] [1]])"]
["distinct" "[1 2 3]" "(distinct [1 1 2 3 3])"]
["dedupe" "[1 2 1]" "(dedupe [1 1 2 1])"]
["interpose" "[1 0 2 0 3]" "(interpose 0 [1 2 3])"]
["interleave" "[1 :a 2 :b]" "(interleave [1 2] [:a :b])"]
["flatten" "[1 2 3 4]" "(flatten [1 [2 [3 [4]]]])"]
["concat" "[1 2 3 4]" "(concat [1 2] [3 4])"]
["into vector" "[1 2 3 4]" "(into [1 2] [3 4])"]
["into list" "[3 2 1]" "(into (list) [1 2 3])"]
["frequencies" "{1 2, 2 1}" "(frequencies [1 1 2])"]
["group-by" "{false [1 3], true [2 4]}" "(group-by even? [1 2 3 4])"]
["zipmap" "{:a 1, :b 2}" "(zipmap [:a :b] [1 2])"]
["mapcat seqs" "[1 2 3 4]" "(mapcat identity [[1 2] [3 4]])"])
(defspec "seq / generators"
["range n" "[0 1 2 3]" "(range 4)"]
["range from to" "[2 3 4]" "(range 2 5)"]
["range with step" "[0 2 4]" "(range 0 6 2)"]
["take repeat" "[:x :x :x]" "(take 3 (repeat :x))"]
["repeat n" "[5 5]" "(repeat 2 5)"]
["take iterate" "[1 2 4 8]" "(take 4 (iterate (fn [x] (* x 2)) 1))"]
["take cycle" "[1 2 1 2 1]" "(take 5 (cycle [1 2]))"]
["take repeatedly" "3" "(count (take 3 (repeatedly (fn [] 1))))"]
["take-last of range" "[8 9]" "(take-last 2 (range 10))"])

35
test/spec/sets-spec.janet Normal file
View file

@ -0,0 +1,35 @@
# Specification: sets, including clojure.set.
(use ../support/harness)
(defspec "set / construct & predicate"
["literal" "#{1 2 3}" "#{1 2 3}"]
["hash-set" "#{1 2 3}" "(hash-set 1 2 3)"]
["set from vector" "#{1 2 3}" "(set [1 2 3 1])"]
["empty" "#{}" "#{}"]
["set? true" "true" "(set? #{1})"]
["set? false on vector" "false" "(set? [1])"]
["count dedups" "3" "(count (set [1 1 2 3]))"]
["equality order-indep" "true" "(= #{1 2 3} #{3 2 1})"])
(defspec "set / operations"
["conj adds" "#{1 2 3}" "(conj #{1 2} 3)"]
["conj dup no-op" "#{1 2}" "(conj #{1 2} 1)"]
["disj removes" "#{1 2}" "(disj #{1 2 3} 3)"]
["disj missing no-op" "#{1 2}" "(disj #{1 2} 9)"]
["contains?" "true" "(contains? #{1 2} 1)"]
["contains? missing" "false" "(contains? #{1 2} 9)"]
["get present" "1" "(get #{1 2} 1)"]
["get missing nil" "nil" "(get #{1 2} 9)"]
["set as fn present" "2" "(#{1 2 3} 2)"]
["set as fn missing" "nil" "(#{1 2 3} 9)"])
(defspec "clojure.set"
["union" "#{1 2 3 4}" "(do (require (quote [clojure.set :as s])) (s/union #{1 2} #{3 4}))"]
["intersection" "#{2}" "(do (require (quote [clojure.set :as s])) (s/intersection #{1 2} #{2 3}))"]
["difference" "#{1}" "(do (require (quote [clojure.set :as s])) (s/difference #{1 2} #{2 3}))"]
["subset? true" "true" "(do (require (quote [clojure.set :as s])) (s/subset? #{1} #{1 2}))"]
["superset? true" "true" "(do (require (quote [clojure.set :as s])) (s/superset? #{1 2} #{1}))"]
["select" "#{2 4}" "(do (require (quote [clojure.set :as s])) (s/select even? #{1 2 3 4}))"]
["join" "#{{:a 1, :b 2, :c 3}}" "(do (require (quote [clojure.set :as s])) (s/join #{{:a 1 :b 2}} #{{:b 2 :c 3}}))"]
["map-invert" "{1 :a}" "(do (require (quote [clojure.set :as s])) (s/map-invert {:a 1}))"]
["rename-keys" "{:b 1}" "(do (require (quote [clojure.set :as s])) (s/rename-keys {:a 1} {:a :b}))"])

View file

@ -0,0 +1,49 @@
# Specification: vectors (persistent, indexed).
(use ../support/harness)
(defspec "vector / construct & predicate"
["literal" "[1 2 3]" "[1 2 3]"]
["vector" "[1 2 3]" "(vector 1 2 3)"]
["vector zero args" "[]" "(vector)"]
["vec from list" "[1 2 3]" "(vec (list 1 2 3))"]
["vec from range" "[0 1 2]" "(vec (range 3))"]
["vec of map yields entries" "[[:a 1]]" "(vec {:a 1})"]
["vector? true" "true" "(vector? [1])"]
["vector? false on list" "false" "(vector? (list 1))"]
["vector = list elts" "true" "(= [1 2 3] (list 1 2 3))"])
(defspec "vector / access"
["nth" ":b" "(nth [:a :b :c] 1)"]
["nth default" ":x" "(nth [:a] 5 :x)"]
["get by index" ":b" "(get [:a :b] 1)"]
["get out of range nil" "nil" "(get [:a] 5)"]
["get default" ":x" "(get [:a] 5 :x)"]
["first" "1" "(first [1 2 3])"]
["last" "3" "(last [1 2 3])"]
["peek is last" "3" "(peek [1 2 3])"]
["count" "3" "(count [1 2 3])"]
["contains? index" "true" "(contains? [:a :b] 1)"]
["contains? past end" "false" "(contains? [:a] 3)"]
["vector as fn" ":b" "([:a :b :c] 1)"])
(defspec "vector / update (persistent)"
["conj appends" "[1 2 3]" "(conj [1 2] 3)"]
["conj many" "[1 2 3 4]" "(conj [1 2] 3 4)"]
["assoc index" "[1 9 3]" "(assoc [1 2 3] 1 9)"]
["assoc at count appends" "[1 2 3]" "(assoc [1 2] 2 3)"]
["update" "[1 3 3]" "(update [1 2 3] 1 inc)"]
["pop drops last" "[1 2]" "(pop [1 2 3])"]
["subvec start end" "[2 3]" "(subvec [1 2 3 4] 1 3)"]
["subvec to end" "[3 4]" "(subvec [1 2 3 4] 2)"]
["mapv" "[2 3 4]" "(mapv inc [1 2 3])"]
["filterv" "[2 4]" "(filterv even? [1 2 3 4])"])
(defspec "vector / immutability & nesting"
["conj does not mutate" "true" "(let [v [1 2] w (conj v 3)] (and (= v [1 2]) (= w [1 2 3])))"]
["assoc does not mutate" "true" "(let [v [1 2 3] w (assoc v 0 9)] (and (= v [1 2 3]) (= w [9 2 3])))"]
["get-in" "2" "(get-in [[1 2] [3 4]] [0 1])"]
["assoc-in" "[[1 9]]" "(assoc-in [[1 2]] [0 1] 9)"]
["update-in" "[[1 3]]" "(update-in [[1 2]] [0 1] inc)"]
["large vector nth" "1500" "(nth (vec (range 2000)) 1500)"]
["large vector count" "2000" "(count (vec (range 2000)))"]
["large conj immutable" "true" "(let [v (vec (range 1000)) w (conj v :end)] (and (= 1000 (count v)) (= 1001 (count w))))"])