Merge pull request #246 from jolt-lang/fix/conj-on-lazyseq
Fix two regressions from the lazy-seq / deftype work (#245)
This commit is contained in:
commit
ab63966ab6
5 changed files with 39 additions and 1 deletions
|
|
@ -49,6 +49,13 @@
|
|||
(cseq-lazy x (lambda () (force-lazyseq coll)))
|
||||
(%ls-cons x coll))))
|
||||
|
||||
;; (conj lazyseq x): conj onto a seq prepends, like any seq — (conj (rest xs) y).
|
||||
;; rest returns a lazyseq, so this is a common path; without it conj reports the
|
||||
;; lazyseq as an "unsupported collection".
|
||||
(define %ls-conj1 jolt-conj1)
|
||||
(set! jolt-conj1 (lambda (coll x)
|
||||
(if (jolt-lazyseq? coll) (jolt-cons x coll) (%ls-conj1 coll x))))
|
||||
|
||||
;; A lazyseq is a NEW value type, so the dispatchers that DON'T route through
|
||||
;; jolt-seq must learn it or a raw (unrealized) lazyseq escapes — e.g. the corpus
|
||||
;; compares (= [1 3 5] (take-nth 2 …)) against the raw lazyseq, and jolt=2 would
|
||||
|
|
|
|||
|
|
@ -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))))
|
||||
|
||||
|
|
|
|||
|
|
@ -161,6 +161,7 @@
|
|||
(cond
|
||||
((procedure? f) (apply f args))
|
||||
((keyword? f) (apply jolt-get (car args) f (cdr args))) ; (:k m [d]) -> (get m :k [d])
|
||||
((jolt-symbol? f) (apply jolt-get (car args) f (cdr args))) ; ('s m [d]) -> (get m 's [d])
|
||||
((jolt-coll? f) (apply jolt-get f args)) ; (coll k [d]) -> (get coll k [d])
|
||||
((jolt-transient? f) (apply jolt-get f args)) ; a transient vec/map/set is callable on the JVM
|
||||
;; a record/reify implementing clojure.lang.IFn is callable: dispatch to its
|
||||
|
|
|
|||
|
|
@ -3278,4 +3278,22 @@
|
|||
{:suite "interop / uri equality" :label "URIs are value-equal and usable as set members" :expected "[true true]" :actual "[(= (java.net.URI. \"/\") (java.net.URI. \"/\")) (= #{(java.net.URI. \"/\")} #{(java.net.URI. \"/\")})]"}
|
||||
{:suite "stdlib / clojure.walk" :label "macroexpand-all expands a form" :expected "true" :actual "(do (require (quote clojure.walk)) (seq? (clojure.walk/macroexpand-all (quote (when true 1)))))"}
|
||||
{:suite "regex / re-seq zero-width" :label "a zero-width match advances by one without repeating" :expected "[\"a\" \"\" \"a\" \"\"]" :actual "(vec (re-seq #\"a*\" \"aba\"))"}
|
||||
{:suite "seqs / lazy-seq interop" :label "conj onto a rest-derived seq prepends" :expected "true" :actual "(= [9 2 3] (vec (conj (rest [1 2 3]) 9)))"}
|
||||
{:suite "seqs / lazy-seq interop" :label "conj onto a lazy-seq prepends" :expected "true" :actual "(= [9 1 2] (vec (conj (lazy-seq (list 1 2)) 9)))"}
|
||||
{:suite "seqs / lazy-seq interop" :label "into over a conj'd rest-seq" :expected "true" :actual "(= [0 2 3] (into [] (conj (rest [1 2 3]) 0)))"}
|
||||
{:suite "seqs / lazy-seq interop" :label "first of a conj'd rest-seq" :expected "true" :actual "(= 9 (first (conj (rest [1 2 3]) 9)))"}
|
||||
{:suite "seqs / lazy-seq interop" :label "count of a conj'd rest-seq" :expected "true" :actual "(= 3 (count (conj (rest [1 2 3]) 9)))"}
|
||||
{:suite "seqs / lazy-seq interop" :label "nth into a rest-seq" :expected "true" :actual "(= 3 (nth (rest [1 2 3]) 1))"}
|
||||
{:suite "seqs / lazy-seq interop" :label "reduce over a rest-seq" :expected "true" :actual "(= 5 (reduce + (rest [1 2 3])))"}
|
||||
{:suite "seqs / lazy-seq interop" :label "a rest-seq equals the literal tail" :expected "true" :actual "(= (quote (2 3)) (rest [1 2 3]))"}
|
||||
{:suite "seqs / lazy-seq interop" :label "map over a rest-seq" :expected "true" :actual "(= [3 4] (vec (map inc (rest [1 2 3]))))"}
|
||||
{:suite "seqs / lazy-seq interop" :label "filter over a rest-seq" :expected "true" :actual "(= [3] (vec (filter odd? (rest [1 2 3 4]))))"}
|
||||
{:suite "seqs / lazy-seq interop" :label "apply over a rest-seq" :expected "true" :actual "(= 5 (apply + (rest [1 2 3])))"}
|
||||
{:suite "seqs / lazy-seq interop" :label "seq of an empty rest is nil" :expected "true" :actual "(nil? (seq (rest [1])))"}
|
||||
{:suite "seqs / lazy-seq interop" :label "empty? of an empty rest" :expected "true" :actual "(empty? (rest [1]))"}
|
||||
{:suite "seqs / lazy-seq interop" :label "cons onto a rest-seq" :expected "true" :actual "(= [0 2 3] (vec (cons 0 (rest [1 2 3]))))"}
|
||||
{:suite "seqs / lazy-seq interop" :label "into a set from a rest-seq" :expected "true" :actual "(= #{2 3} (into #{} (rest [1 2 3])))"}
|
||||
{:suite "ifn / symbol as fn" :label "a symbol invokes as a map lookup" :expected "true" :actual "(= 5 ('a {(quote a) 5}))"}
|
||||
{:suite "ifn / symbol as fn" :label "a symbol fn takes a not-found default" :expected "true" :actual "(= :d ('a {} :d))"}
|
||||
{:suite "ifn / symbol as fn" :label "a symbol works as a mapping fn" :expected "true" :actual "(= [1 2] (vec (map (quote k) [{(quote k) 1} {(quote k) 2}])))"}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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]"}
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue