fix: lazy iterate/range(infinite)/single-coll-map over lazy input; realize lazy-seqs in reduce/filter

This commit is contained in:
Yogthos 2026-06-04 14:06:02 -04:00
parent 2ea5b2bb5f
commit 3c77f6a9c0
3 changed files with 46 additions and 32 deletions

View file

@ -1,2 +1,4 @@
{"id":"int-621ea914","kind":"field_change","created_at":"2026-06-04T17:50:54.012588Z","actor":"Yogthos","issue_id":"jolt-x8s","extra":{"field":"status","new_value":"closed","old_value":"open"}}
{"id":"int-978620fa","kind":"field_change","created_at":"2026-06-04T17:59:35.53184Z","actor":"Yogthos","issue_id":"jolt-lp5","extra":{"field":"status","new_value":"closed","old_value":"open"}}
{"id":"int-11c77978","kind":"field_change","created_at":"2026-06-04T18:06:01.464313Z","actor":"Yogthos","issue_id":"jolt-tws","extra":{"field":"status","new_value":"closed","old_value":"open"}}
{"id":"int-2eef7613","kind":"field_change","created_at":"2026-06-04T18:06:02.544998Z","actor":"Yogthos","issue_id":"jolt-wec","extra":{"field":"status","new_value":"closed","old_value":"open"}}

View file

@ -1,6 +1,6 @@
{"_type":"issue","id":"jolt-lp5","title":"CRITICAL: vec/into over lazy-seq leaks PV struct; into {} builds int keys","status":"closed","priority":1,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T17:46:15Z","created_by":"Yogthos","updated_at":"2026-06-04T17:59:35Z","closed_at":"2026-06-04T17:59:35Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"jolt-nte","title":"Build phased Clojure conformance harness (extracted assertions)","status":"open","priority":1,"issue_type":"task","owner":"yogthos@gmail.com","created_at":"2026-06-04T17:46:15Z","created_by":"Yogthos","updated_at":"2026-06-04T17:46:15Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"jolt-tws","title":"CRITICAL: iterate arity bug","status":"open","priority":1,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T17:46:14Z","created_by":"Yogthos","updated_at":"2026-06-04T17:46:14Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"jolt-tws","title":"CRITICAL: iterate arity bug","status":"closed","priority":1,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T17:46:14Z","created_by":"Yogthos","updated_at":"2026-06-04T18:06:01Z","closed_at":"2026-06-04T18:06:01Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"jolt-x8s","title":"CRITICAL: collections not callable as IFn (vector/map/set)","status":"closed","priority":1,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T17:46:14Z","created_by":"Yogthos","updated_at":"2026-06-04T17:50:54Z","closed_at":"2026-06-04T17:50:54Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"jolt-alz","title":"CRITICAL: self-referential lazy-seq/lazy-cat yields only literal prefix","status":"open","priority":1,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T17:46:13Z","created_by":"Yogthos","updated_at":"2026-06-04T17:46:13Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"jolt-wec","title":"CRITICAL: multi-collection map returns unrealized thunk","status":"open","priority":1,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T17:46:12Z","created_by":"Yogthos","updated_at":"2026-06-04T17:46:12Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"issue","id":"jolt-wec","title":"CRITICAL: multi-collection map returns unrealized thunk","status":"closed","priority":1,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T17:46:12Z","created_by":"Yogthos","updated_at":"2026-06-04T18:06:02Z","closed_at":"2026-06-04T18:06:02Z","dependency_count":0,"dependent_count":0,"comment_count":0}

View file

@ -326,15 +326,30 @@
# ============================================================
(defn- seq-done?
"True when cursor c (a lazy-seq or a concrete collection) is exhausted.
Uses cell realization for lazy-seqs so nil elements don't end the seq early."
[c]
(if (lazy-seq? c)
(let [cell (realize-ls c)]
(or (nil? cell) (= :jolt/pending cell) (= 0 (length cell))))
(or (nil? c) (= 0 (length c)))))
(defn core-map [f & colls]
(if (= 1 (length colls))
# Single-collection: eagerly realized
(let [c (realize-for-iteration (colls 0))
result (do
(var res @[])
(each x c (array/push res (f x)))
res)]
(if (tuple? c) (tuple/slice (tuple ;result)) result))
(let [coll (colls 0)]
(if (lazy-seq? coll)
# Lazy input: stay lazy so infinite/self-referential seqs work.
(do
(defn mstep [c]
(fn []
(if (seq-done? c) nil
@[(f (core-first c)) (mstep (core-rest c))])))
(make-lazy-seq (mstep coll)))
# Concrete collection: eager (preserves tuple/array representation).
(let [c (if (set? coll) (phs-seq coll) coll)
result (do (var res @[]) (each x c (array/push res (f x))) res)]
(if (tuple? c) (tuple/slice (tuple ;result)) result))))
# Multi-collection: lazy-seq with per-element independent state
(let [init-cs (array/new-filled (length colls) nil)
init-idxs (array/new-filled (length colls) 0)
@ -383,7 +398,7 @@
(defn core-filter [pred coll]
(var result @[])
(each x (if (set? coll) (phs-seq coll) coll)
(each x (if (set? coll) (phs-seq coll) (realize-for-iteration coll))
(if (pred x) (array/push result x)))
(if (tuple? coll) (tuple/slice (tuple ;result)) result))
@ -394,7 +409,7 @@
(fn [& args]
(case (length args)
2 (let [f (args 0) coll (args 1)
coll (if (set? coll) (phs-seq coll) coll)]
coll (if (set? coll) (phs-seq coll) (realize-for-iteration coll))]
(if (= 0 (length coll))
(f)
(do
@ -405,7 +420,7 @@
(++ i))
acc)))
3 (let [f (args 0) val (args 1) coll (args 2)
coll (if (set? coll) (phs-seq coll) coll)]
coll (if (set? coll) (phs-seq coll) (realize-for-iteration coll))]
(var acc val)
(each x coll (set acc (f acc x)))
acc)
@ -637,15 +652,20 @@
(def core-range
(fn [& args]
(let [start (if (> (length args) 1) (args 0) 0)
end (if (> (length args) 1) (args 1) (args 0))
step (if (> (length args) 2) (args 2) 1)]
(var result @[])
(var i start)
(while (if (pos? step) (< i end) (> i end))
(array/push result i)
(+= i step))
(tuple/slice (tuple ;result)))))
(if (= 0 (length args))
# (range) — infinite lazy sequence 0, 1, 2, ...
(do
(defn rstep [i] (fn [] @[i (rstep (+ i 1))]))
(make-lazy-seq (rstep 0)))
(let [start (if (> (length args) 1) (args 0) 0)
end (if (> (length args) 1) (args 1) (args 0))
step (if (> (length args) 2) (args 2) 1)]
(var result @[])
(var i start)
(while (if (pos? step) (< i end) (> i end))
(array/push result i)
(+= i step))
(tuple/slice (tuple ;result))))))
(def core-repeat (fn [n x]
(var result @[])
@ -656,17 +676,9 @@
result))
(defn core-iterate [f x]
"Macro: (iterate f x) → lazy infinite sequence x, (f x), (f (f x)), ..."
(def sym-x (gensym "x"))
(def sym-f (gensym "f"))
@[{:jolt/type :symbol :ns nil :name "lazy-seq"}
@[{:jolt/type :symbol :ns nil :name "let*"}
@[sym-x x sym-f f]
@[{:jolt/type :symbol :ns nil :name "cons"}
sym-x
@[{:jolt/type :symbol :ns nil :name "iterate"}
sym-f
@[{:jolt/type :symbol :ns nil :name sym-f} sym-x]]]]])
"Lazy infinite sequence x, (f x), (f (f x)), ..."
(defn istep [v] (fn [] @[v (istep (f v))]))
(make-lazy-seq (istep x)))
(defn core-repeatedly [n f]
(var result @[])