diff --git a/.beads/interactions.jsonl b/.beads/interactions.jsonl index 19cbd6e..1c685e5 100644 --- a/.beads/interactions.jsonl +++ b/.beads/interactions.jsonl @@ -2,3 +2,5 @@ {"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"}} +{"id":"int-a7573343","kind":"field_change","created_at":"2026-06-04T18:09:14.608401Z","actor":"Yogthos","issue_id":"jolt-alz","extra":{"field":"status","new_value":"closed","old_value":"open"}} +{"id":"int-40cd8348","kind":"field_change","created_at":"2026-06-04T18:09:15.510649Z","actor":"Yogthos","issue_id":"jolt-nte","extra":{"field":"status","new_value":"closed","old_value":"open"}} diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl index e5cece0..6d67bb0 100644 --- a/.beads/issues.jsonl +++ b/.beads/issues.jsonl @@ -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-nte","title":"Build phased Clojure conformance harness (extracted assertions)","status":"closed","priority":1,"issue_type":"task","owner":"yogthos@gmail.com","created_at":"2026-06-04T17:46:15Z","created_by":"Yogthos","updated_at":"2026-06-04T18:09:15Z","closed_at":"2026-06-04T18:09:15Z","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-alz","title":"CRITICAL: self-referential lazy-seq/lazy-cat yields only literal prefix","status":"closed","priority":1,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T17:46:13Z","created_by":"Yogthos","updated_at":"2026-06-04T18:09:15Z","closed_at":"2026-06-04T18:09:15Z","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} diff --git a/src/jolt/core.janet b/src/jolt/core.janet index ddac0ae..67e74f3 100644 --- a/src/jolt/core.janet +++ b/src/jolt/core.janet @@ -499,25 +499,26 @@ nil))))) (defn core-concat [& colls] - "Lazy concatenation. Each rest-thunk captures its own (cur, cs) state - so that independent traversal paths do not corrupt each other." + "Truly lazy concatenation. `step` returns a 0-arg thunk that is only forced + when the consumer asks for the next cell, so nothing in `colls` is realized at + construction time. This is essential for self-referential lazy seqs (e.g. + (def fib (lazy-cat [0 1] (map + (rest fib) fib)))): the later colls must not be + forced until after the surrounding `def` has bound the var." (defn step [cs] - (if (= 0 (length cs)) - (fn [] nil) - (let [c (in cs 0) - remaining (array/slice cs 1)] - (if (lazy-seq? c) - (let [val (ls-first c)] - (if (nil? val) (step remaining) - (let [rest-ls (ls-rest c) - next-step (step (array/insert remaining 0 rest-ls))] - (fn [] @[val next-step])))) - (let [cell (coll->cells c)] - (if (nil? cell) (step remaining) - (let [rest-fn (in cell 1) - next-step (if (nil? rest-fn) (step remaining) - (step (array/insert remaining 0 rest-fn)))] - (fn [] @[(in cell 0) next-step])))))))) + (fn [] + (if (= 0 (length cs)) + nil + (let [c (in cs 0) + remaining (array/slice cs 1) + cell (coll->cells c)] + (if (nil? cell) + # current coll is empty: advance to the next one + ((step remaining)) + (let [val (in cell 0) + rest-fn (in cell 1)] + @[val (step (if (nil? rest-fn) + remaining + (array/insert remaining 0 rest-fn)))])))))) (make-lazy-seq (step (if (tuple? colls) (array/slice colls) colls)))) (defn core-reverse [coll]