feat(strictness): assoc bounds, dissoc/count map-only, subvec bounds, numerator/denominator, min-key empty

- assoc on a vector bounds-checks the index (0..count); out-of-range/negative throw
- dissoc throws on non-maps (numbers/sequences/sets/scalars); nil ok; records/
  sorted-maps/meta-maps still handled
- count throws on scalars (numbers/keywords/symbols/booleans/chars)
- subvec validates vector type and 0<=start<=end<=count
- numerator/denominator always throw (Jolt has no ratio type)
- min-key/max-key throw on no values

count 18/2; dissoc 19/3; assoc 36/6; subvec 26/3/5; numerator/denominator throw
cases pass. clojure-test-suite pass 3840->3864. spec: map/strictness (16). jpm test green.
This commit is contained in:
Yogthos 2026-06-05 13:44:37 -04:00
parent b82477dac3
commit ff3cc7d6c0
3 changed files with 57 additions and 9 deletions

View file

@ -18,7 +18,7 @@
# Baseline: assertions Jolt currently passes across the suite. Raise as Jolt
# improves so a regression (previously-passing assertion breaking) is caught.
(def baseline-pass 3835)
(def baseline-pass 3860)
# A file is "clean" when it ran with zero failures AND zero errors.
(def baseline-clean-files 45)
# Per-file wall-clock budget (seconds). Normal files finish in well under 1s;

View file

@ -71,3 +71,23 @@
["key across repr" ":v" "(get (assoc {} (vec [1 2]) :v) [1 2])"]
["frequencies of maps" "2" "(get (frequencies [{:a 1} (hash-map :a 1)]) {:a 1})"]
["group-by collection key" "1" "(count (group-by identity [{:a 1} (hash-map :a 1)]))"])
# Strictness: assoc bounds-checks vector indices; dissoc requires a map;
# count rejects scalars; numerator/denominator have no ratio type.
(defspec "map / strictness (throws like Clojure)"
["assoc vec out of bounds" :throws "(assoc [0 1 2] 4 4)"]
["assoc vec negative" :throws "(assoc [] -1 0)"]
["assoc vec at count ok" "[1 2 3]" "(assoc [1 2] 2 3)"]
["dissoc on number" :throws "(dissoc 42 :a)"]
["dissoc on vector" :throws "(dissoc [1 2] 0)"]
["dissoc on set" :throws "(dissoc #{:a} :a)"]
["dissoc nil ok" "nil" "(dissoc nil :a)"]
["count on number" :throws "(count 1)"]
["count on keyword" :throws "(count :a)"]
["count string ok" "3" "(count \"abc\")"]
["numerator throws" :throws "(numerator 1)"]
["denominator throws" :throws "(denominator 2)"]
["subvec out of range" :throws "(subvec [0 1 2 3] 1 5)"]
["subvec start>end" :throws "(subvec [0 1 2 3] 3 2)"]
["subvec ok" "[1 2]" "(subvec [0 1 2 3] 1 3)"]
["min-key empty" :throws "(apply min-key identity [])"])