feat(strictness): first/rseq shape checks, assoc even-args + non-associative
- first throws on scalars (numbers/keywords/booleans/char & symbol structs) - rseq is vector/sorted-only (throws on strings/maps/numbers/seqs) - assoc requires an even kv count and a map/vector/nil receiver first clean; rseq 12/1; assoc 39/3. clojure-test-suite pass 3864->3874. spec: seq/more-strictness (11). jpm test green.
This commit is contained in:
parent
ff3cc7d6c0
commit
2ca3fa4348
3 changed files with 36 additions and 5 deletions
|
|
@ -342,6 +342,13 @@
|
|||
result)))))))))))
|
||||
|
||||
(defn core-assoc [m & kvs]
|
||||
(when (odd? (length kvs))
|
||||
(error "assoc expects an even number of key/value arguments"))
|
||||
# assoc is defined on maps, vectors and nil; reject other shapes
|
||||
(when (or (number? m) (string? m) (buffer? m) (keyword? m) (boolean? m)
|
||||
(plist? m) (set? m) (core-transient? m)
|
||||
(and (struct? m) (get m :jolt/type)))
|
||||
(error (string "assoc requires a map or vector, got " (type m))))
|
||||
(cond
|
||||
(phm? m)
|
||||
(do (var result m) (var i 0) (while (< i (length kvs)) (set result (phm-assoc result (kvs i) (kvs (+ i 1)))) (+= i 2)) result)
|
||||
|
|
@ -527,9 +534,14 @@
|
|||
# maps and sets: first of their seq (an entry / element)
|
||||
(phm? coll) (let [e (phm-entries coll)] (if (= 0 (length e)) nil (in e 0)))
|
||||
(set? coll) (let [s (phs-seq coll)] (if (= 0 (length s)) nil (in s 0)))
|
||||
(struct? coll) (let [ks (keys coll)] (if (= 0 (length ks)) nil (tuple (in ks 0) (get coll (in ks 0)))))
|
||||
(or (nil? coll) (= 0 (length coll))) nil
|
||||
(string? coll) (make-char (in coll 0))
|
||||
(and (struct? coll) (nil? (get coll :jolt/type)))
|
||||
(let [ks (keys coll)] (if (= 0 (length ks)) nil (tuple (in ks 0) (get coll (in ks 0)))))
|
||||
(nil? coll) nil
|
||||
(string? coll) (if (= 0 (length coll)) nil (make-char (in coll 0)))
|
||||
# scalars aren't seqable
|
||||
(or (number? coll) (boolean? coll) (keyword? coll) (and (struct? coll) (get coll :jolt/type)))
|
||||
(error (string "first not supported on " (type coll)))
|
||||
(= 0 (length coll)) nil
|
||||
(in coll 0)))
|
||||
|
||||
(defn core-rest [coll]
|
||||
|
|
@ -2972,8 +2984,13 @@
|
|||
(defn core-not-empty [coll]
|
||||
(if (or (nil? coll) (= 0 (core-count coll))) nil coll))
|
||||
|
||||
# rseq is defined only on vectors and sorted collections (Reversible).
|
||||
(defn core-rseq [coll]
|
||||
(let [c (realize-for-iteration coll)] (tuple/slice (tuple ;(reverse c)))))
|
||||
(cond
|
||||
(pvec? coll) (tuple/slice (tuple ;(reverse (pv->array coll))))
|
||||
(core-sorted-map? coll) (tuple/slice (tuple ;(reverse (sorted-map-entries coll))))
|
||||
(core-sorted-set? coll) (tuple/slice (tuple ;(reverse (coll :items))))
|
||||
(error (string "rseq requires a vector or sorted collection, got " (type coll)))))
|
||||
|
||||
(defn core-shuffle [coll]
|
||||
(let [c (array/slice (realize-for-iteration coll))]
|
||||
|
|
|
|||
|
|
@ -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 3860)
|
||||
(def baseline-pass 3870)
|
||||
# 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;
|
||||
|
|
|
|||
|
|
@ -165,3 +165,17 @@
|
|||
["val on number" :throws "(val 0)"]
|
||||
["key of entry" ":a" "(key (first {:a 1}))"]
|
||||
["val of entry" "1" "(val (first {:a 1}))"])
|
||||
|
||||
# More strictness: first/rseq on the right shapes, assoc even-arg requirement.
|
||||
(defspec "seq / more strictness"
|
||||
["first on number" :throws "(first 42)"]
|
||||
["first on keyword" :throws "(first :a)"]
|
||||
["first ok vec" "1" "(first [1 2])"]
|
||||
["first ok nil" "nil" "(first nil)"]
|
||||
["rseq vector" "[3 2 1]" "(rseq [1 2 3])"]
|
||||
["rseq on string" :throws "(rseq \"ab\")"]
|
||||
["rseq on map" :throws "(rseq {:a 1})"]
|
||||
["rseq on number" :throws "(rseq 0)"]
|
||||
["assoc odd args" :throws "(assoc {:a 1} :b)"]
|
||||
["assoc on number" :throws "(assoc 5 :a 1)"]
|
||||
["assoc on set" :throws "(assoc #{} :a 1)"])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue