clojure.walk: preserve record types
walk treated a record as a plain map (record? implies map?), rebuilding it via (into (empty form) ...) which yields a bare map and drops the type. Add a record branch before the map branch that conj-es the walked entries back onto the original, matching JVM clojure.walk's IRecord case. Type-dispatched walks need it — integrant resolves #ig/ref by detecting its Ref record while postwalking the config, so without this every ref silently fails to resolve. clojure.walk is baked into the prelude, so the seed is re-minted. Corpus gains five JVM-certified rows for record type/instance? survival through pre/postwalk.
This commit is contained in:
parent
54c3c6dd2b
commit
ea609d72eb
4 changed files with 670 additions and 660 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -7,6 +7,11 @@
|
||||||
; vectors/maps first so seq? can't swallow them (a vector is not seq? on
|
; vectors/maps first so seq? can't swallow them (a vector is not seq? on
|
||||||
; jolt, but keep the concrete branches authoritative)
|
; jolt, but keep the concrete branches authoritative)
|
||||||
(vector? form) (outer (vec (map inner form)))
|
(vector? form) (outer (vec (map inner form)))
|
||||||
|
; a record is also map?, but (empty record) yields a plain map — rebuild by
|
||||||
|
; conj-ing the walked entries back onto the original so the record TYPE
|
||||||
|
; survives. Type-dispatched walks depend on it (e.g. integrant resolves
|
||||||
|
; #ig/ref by detecting its Ref record while postwalking the config).
|
||||||
|
(record? form) (outer (reduce (fn [r x] (conj r (inner x))) form form))
|
||||||
(map? form) (outer (into (empty form) (map inner form)))
|
(map? form) (outer (into (empty form) (map inner form)))
|
||||||
; lists rebuild as lists, other seqs (incl. macro/template output: cons/
|
; lists rebuild as lists, other seqs (incl. macro/template output: cons/
|
||||||
; concat/lazy-seq) walk too — without this, postwalk-replace silently no-op'd
|
; concat/lazy-seq) walk too — without this, postwalk-replace silently no-op'd
|
||||||
|
|
|
||||||
|
|
@ -2640,6 +2640,11 @@
|
||||||
{:suite "clojure.walk / lists + seqs" :label "postwalk-replace in a vector" :expected "[:one 2 :one]" :actual "(do (require (quote [clojure.walk :as w])) (w/postwalk-replace {1 :one} [1 2 1]))"}
|
{:suite "clojure.walk / lists + seqs" :label "postwalk-replace in a vector" :expected "[:one 2 :one]" :actual "(do (require (quote [clojure.walk :as w])) (w/postwalk-replace {1 :one} [1 2 1]))"}
|
||||||
{:suite "clojure.walk / lists + seqs" :label "keywordize-keys still works" :expected "{:a 1}" :actual "(do (require (quote [clojure.walk :as w])) (w/keywordize-keys {\"a\" 1}))"}
|
{:suite "clojure.walk / lists + seqs" :label "keywordize-keys still works" :expected "{:a 1}" :actual "(do (require (quote [clojure.walk :as w])) (w/keywordize-keys {\"a\" 1}))"}
|
||||||
{:suite "clojure.walk / lists + seqs" :label "apply-template substitutes" :expected "(quote (+ 1 2))" :actual "(do (require (quote [clojure.template :as t])) (t/apply-template (quote [x y]) (quote (+ x y)) (quote (1 2))))"}
|
{:suite "clojure.walk / lists + seqs" :label "apply-template substitutes" :expected "(quote (+ 1 2))" :actual "(do (require (quote [clojure.template :as t])) (t/apply-template (quote [x y]) (quote (+ x y)) (quote (1 2))))"}
|
||||||
|
{:suite "clojure.walk / records keep their type" :label "postwalk preserves record type" :expected "true" :actual "(do (require (quote [clojure.walk :as w])) (defrecord R [a]) (record? (w/postwalk identity (->R 1))))"}
|
||||||
|
{:suite "clojure.walk / records keep their type" :label "postwalk still walks record fields" :expected "2" :actual "(do (require (quote [clojure.walk :as w])) (defrecord R [a]) (:a (w/postwalk (fn [x] (if (number? x) (inc x) x)) (->R 1))))"}
|
||||||
|
{:suite "clojure.walk / records keep their type" :label "instance? survives a walk" :expected "true" :actual "(do (require (quote [clojure.walk :as w])) (defrecord R [a]) (instance? R (w/postwalk identity (->R 1))))"}
|
||||||
|
{:suite "clojure.walk / records keep their type" :label "a record nested in a map keeps its type" :expected "true" :actual "(do (require (quote [clojure.walk :as w])) (defrecord R [a]) (record? (:r (w/postwalk identity {:r (->R 1)}))))"}
|
||||||
|
{:suite "clojure.walk / records keep their type" :label "prewalk preserves record type" :expected "true" :actual "(do (require (quote [clojure.walk :as w])) (defrecord R [a]) (record? (w/prewalk identity (->R 1))))"}
|
||||||
{:suite "conformance / CRITICAL: lazy sequences" :label "self-ref lazy-cat fib" :expected "[0 1 1 2 3 5 8 13 21 34]" :actual "(do (def fib-seq (lazy-cat [0 1] (map + (rest fib-seq) fib-seq))) (take 10 fib-seq))"}
|
{:suite "conformance / CRITICAL: lazy sequences" :label "self-ref lazy-cat fib" :expected "[0 1 1 2 3 5 8 13 21 34]" :actual "(do (def fib-seq (lazy-cat [0 1] (map + (rest fib-seq) fib-seq))) (take 10 fib-seq))"}
|
||||||
{:suite "conformance / CRITICAL: multi-collection map" :label "map two colls" :expected "[11 22 33]" :actual "(map + [1 2 3] [10 20 30])"}
|
{:suite "conformance / CRITICAL: multi-collection map" :label "map two colls" :expected "[11 22 33]" :actual "(map + [1 2 3] [10 20 30])"}
|
||||||
{:suite "conformance / CRITICAL: multi-collection map" :label "map three colls" :expected "[12 24 36]" :actual "(map + [1 2 3] [10 20 30] [1 2 3])"}
|
{:suite "conformance / CRITICAL: multi-collection map" :label "map three colls" :expected "[12 24 36]" :actual "(map + [1 2 3] [10 20 30] [1 2 3])"}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue