fix: conj 0-arg, conj onto nil (builds list), conj map into map

- (conj) -> []
- (conj nil x ...) builds a list (prepends): (conj nil 1 2) -> (2 1)
- conj a map value into a map/phm merges its entries ((conj {:a 0} {:b 1}) ->
  {:a 0 :b 1}); a [k v] vector/pair still adds one entry.

conj.cljc 14/6/5 -> 21/3/1. clojure-test-suite pass 3681->3691, errors 105->98.
spec: seq/conj-edge-cases (8). jpm test green.
This commit is contained in:
Yogthos 2026-06-05 10:30:07 -04:00
parent a4d9d5f70b
commit 66c8c1157b
3 changed files with 33 additions and 13 deletions

View file

@ -283,7 +283,16 @@
# Collections
# ============================================================
(defn core-conj [coll & xs]
# Is x a map value (for conj/merge semantics: conj-ing a map merges its entries)?
(defn- map-value? [x]
(or (phm? x) (and (struct? x) (nil? (get x :jolt/type)))))
(defn core-conj [& args]
(if (= 0 (length args)) (make-vec @[]) # (conj) -> []
(let [coll (first args) xs (tuple/slice args 1)]
(if (nil? coll)
# conj onto nil builds a list (prepends): (conj nil 1 2) -> (2 1)
(do (var result nil) (each x xs (set result (pl-cons x result))) result)
(if (pvec? coll)
(do (var result coll) (each x xs (set result (pv-conj result x))) result)
(if (plist? coll)
@ -303,20 +312,20 @@
(if (phm? coll)
(do
(var result coll)
(var i 0)
(while (< i (length xs))
(let [pair (xs i)]
(set result (phm-assoc result (vnth pair 0) (vnth pair 1))))
(++ i))
(each x xs
(if (map-value? x)
# conj a map -> merge its entries
(each k (if (phm? x) (keys (phm-to-struct x)) (keys x))
(set result (phm-assoc result k (if (phm? x) (phm-get x k) (in x k)))))
(set result (phm-assoc result (vnth x 0) (vnth x 1)))))
result)
(do
(var result coll)
(var i 0)
(while (< i (length xs))
(let [pair (xs i)]
(set result (merge result {(vnth pair 0) (vnth pair 1)})))
(++ i))
result))))))))
(each x xs
(if (map-value? x)
(set result (merge result (if (phm? x) (phm-to-struct x) x)))
(set result (merge result {(vnth x 0) (vnth x 1)}))))
result)))))))))))
(defn core-assoc [m & kvs]
(cond

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 3680)
(def baseline-pass 3690)
# 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

@ -118,3 +118,14 @@
["map a map" "[1 nil 2]" "(map {:a 1 :b 2} [:a :z :b])"]
["take-nth transducer" "[0 2 4 6 8]" "(into [] (take-nth 2) (range 10))"]
["interpose transducer" "[1 :x 2]" "(into [] (interpose :x) [1 2])"])
# conj edge cases: 0-arg, conj onto nil (builds a list), conj a map into a map.
(defspec "seq / conj edge cases"
["conj no args" "[]" "(conj)"]
["conj nil one" "[3]" "(conj nil 3)"]
["conj nil many" "[2 1]" "(conj nil 1 2)"]
["conj vector" "[1 2 3]" "(conj [1 2] 3)"]
["conj list prepend" "[0 1 2]" "(conj '(1 2) 0)"]
["conj map + map" "{:a 0, :b 1}" "(conj {:a 0} {:b 1})"]
["conj map + pair" "{:a 0, :b 1}" "(conj {:a 0} [:b 1])"]
["conj map merge wins" "{:a 2}" "(conj {:a 0} {:a 1} {:a 2})"])