diff --git a/host/chez/records.ss b/host/chez/records.ss index 00b0a95..66fdc57 100644 --- a/host/chez/records.ss +++ b/host/chez/records.ss @@ -58,6 +58,14 @@ (find-method-any-protocol tag "valAt") (find-method-any-protocol tag "cons")))) #t)) +;; a jrec that is map? — a record, or a deftype implementing clojure.lang +;; .IPersistentMap (clojure.core.cache's caches do). `without` (dissoc) is the +;; map-distinctive method: vectors/sets implement Associative/ILookup but not it. +(define (jrec-maplike? x) + (and (jrec? x) + (or (jrec-record? x) + (find-method-any-protocol (jrec-tag x) "without")) + #t)) (define jolt-deftype-kw (keyword "jolt" "deftype")) ;; unique present-vs-absent sentinel for extension-map lookups (so a present nil ;; in the extension map is distinguished from a genuine miss). @@ -399,7 +407,7 @@ ;; deftype is not. coll? additionally covers a deftype implementing a collection ;; interface. predicates.ss vars hold a snapshot, so re-def-var! after extending. (define %r-jolt-map? jolt-map?) -(set! jolt-map? (lambda (x) (or (jrec-record? x) (%r-jolt-map? x)))) +(set! jolt-map? (lambda (x) (or (jrec-maplike? x) (%r-jolt-map? x)))) (def-var! "clojure.core" "map?" jolt-map?) (def-var! "clojure.core" "coll?" (lambda (x) (or (jrec-collection? x) (jolt-coll-pred? x)))) diff --git a/test/chez/unit.edn b/test/chez/unit.edn index cb1a1ec..5e85d49 100644 --- a/test/chez/unit.edn +++ b/test/chez/unit.edn @@ -563,4 +563,8 @@ {:suite "bytes" :expr "(String. (byte-array [104 105]) \"UTF-8\")" :expected "hi"} {:suite "bytes" :expr "(int (first (String. (byte-array [200]) \"ISO-8859-1\")))" :expected "200"} {:suite "bytes" :expr "(String. (.getBytes \"round\" \"UTF-8\") \"UTF-8\")" :expected "round"} + {:suite "deftype-map" :expr "(do (deftype Mp [m] clojure.lang.IPersistentMap (without [_ k] m)) [(map? (->Mp 1)) (record? (->Mp 1))])" :expected "[true false]"} + {:suite "deftype-map" :expr "(do (deftype Op [s]) [(map? (->Op 1)) (record? (->Op 1)) (coll? (->Op 1))])" :expected "[false false false]"} + {:suite "deftype-map" :expr "(do (deftype Lc [xs] clojure.lang.Counted (count [_] (count xs)) clojure.lang.Seqable (seq [_] (seq xs))) [(coll? (->Lc [1 2])) (count (->Lc [1 2])) (vec (seq (->Lc [1 2])))])" :expected "[true 2 [1 2]]"} + {:suite "deftype-map" :expr "(do (defrecord Dr [a b]) [(map? (->Dr 1 2)) (record? (->Dr 1 2)) (coll? (->Dr 1 2))])" :expected "[true true true]"} ]