Records are not vectors: vector?/sequential? false for shape-recs (jolt-14k)
Under direct-linking a record is a Janet tuple (its shape-rec), and core-vector?
just delegated to jvec? which is true for any tuple — so (vector? a-record) and
(sequential? a-record) returned true. That broke map-destructuring of a record:
the destructure coerce treats a sequential source as & {:keys} kwargs and does
(apply hash-map x), so destructuring a record fed its entries to make-phm as a
flat kv-list and corrupted. Surfaced as reitit's router crashing on a wildcard
route ('expected integer key for tuple in range [0,5), got 5') whenever the new
direct-link default was on; minimal repro is (let [{:keys [a]} (->R ...)] ...).
Fix: core-vector? excludes shape-recs, matching Clojure (a record is not a
vector or sequential). jvec? is unchanged for internal representation dispatch.
Regression cases added to record-declared-shape-test.
This commit is contained in:
parent
8c29168de2
commit
8a3019a64e
2 changed files with 13 additions and 2 deletions
|
|
@ -204,7 +204,12 @@
|
|||
(defn core-fn? [x] (or (function? x) (cfunction? x)))
|
||||
(defn core-keyword? [x] (keyword? x))
|
||||
(defn core-symbol? [x] (and (struct? x) (= :symbol (x :jolt/type))))
|
||||
(defn core-vector? [x] (jvec? x))
|
||||
# A record shape-rec is a Janet tuple (jvec? true), but a record is NOT a vector
|
||||
# in Clojure — `(vector? record)` is false, and so is `(sequential? record)`.
|
||||
# Excluding it here keeps map-destructuring of a record off the `& {:keys}` kwargs
|
||||
# coerce path (which does `(apply hash-map x)` for a sequential x). jvec? itself
|
||||
# stays as-is for internal representation dispatch.
|
||||
(defn core-vector? [x] (and (jvec? x) (not (shape-rec? x))))
|
||||
# map? is STRICT: a plain struct map literal, a phm, a sorted map, or a record.
|
||||
# Tagged structs (symbols/chars/uuids — anything with :jolt/type) are VALUES,
|
||||
# not maps. (sorted-map? is defined later, so the table check is inlined.)
|
||||
|
|
|
|||
|
|
@ -29,7 +29,13 @@
|
|||
["record? true" "(do (defrecord Rd [x y]) (record? (->Rd 1 2)))"]
|
||||
["record vs map not=" "(do (defrecord Re [x y]) (not (= (->Re 1 2) {:x 1 :y 2})))"]
|
||||
["assoc keeps type" "(do (defrecord Rf [x y]) (record? (assoc (->Rf 1 2) :x 9)))"]
|
||||
["pr declared order" "(do (defrecord Rg [b a c]) (= \"#user.Rg{:b 10, :a 20, :c 30}\" (pr-str (->Rg 10 20 30))))"]])
|
||||
["pr declared order" "(do (defrecord Rg [b a c]) (= \"#user.Rg{:b 10, :a 20, :c 30}\" (pr-str (->Rg 10 20 30))))"]
|
||||
# a record shape-rec is a Janet tuple, but a record is NOT a vector/sequential
|
||||
# in Clojure — else map-destructuring it takes the kwargs coerce path and
|
||||
# corrupts (reitit router crash, jolt-14k).
|
||||
["vector? record false" "(do (defrecord Rh [x y]) (not (vector? (->Rh 1 2))))"]
|
||||
["sequential? record false" "(do (defrecord Ri [x y]) (not (sequential? (->Ri 1 2))))"]
|
||||
["destructure record :or" "(do (defrecord Rj [a b c d e]) (let [{:keys [a e] :or {a 0}} (->Rj 1 2 3 4 5)] (= 6 (+ a e))))"]])
|
||||
|
||||
(each [label prog] cases
|
||||
(check label (eval-string dl prog) true))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue