mapcat in 10-seq.clj now uses a defn- mapcat-step helper that walks lazy map results element-by-element (cons + lazy-seq), with explicit arities for 1/2/3/4+ colls. The 4+-coll arity still uses apply to spread colls to map, but apply no longer forces the inner map result. Previously (apply concat (apply map f colls)) forced the lazy map result through core-apply realize-for-iteration, which hung on infinite inputs. The new step-based impl walks one element at a time via first/rest/seq primitives. Re-enabled deferred mapcat infinite-input harness case. 19/19 pass. Gates: lazy-infinite 19/19, conformance 229/229 interpret+self-host (compile 228/229 — 1 pre-existing protocol error), specs 32/32.
51 lines
1.7 KiB
Clojure
51 lines
1.7 KiB
Clojure
;; clojure.core — seq tier. Pure-Clojure leaf sequence fns on top of the kernel
|
|
;; tier (00-kernel) and the Janet seed. Loaded after the kernel tier; in compile
|
|
;; mode these self-host through the now-built analyzer (interpreted otherwise).
|
|
;;
|
|
;; Migration rule for adding fns here: the fn must (1) NOT be in
|
|
;; compiler/core-renames (that map emits core-X Janet symbols directly), (2) have
|
|
;; no internal Janet callers of its core-X binding, and (3) NOT be used by the
|
|
;; self-hosted compiler (jolt-core/jolt/*.clj). Compiler-facing structural fns go
|
|
;; in the kernel tier (00-kernel) instead — see its header.
|
|
|
|
(defn ffirst [coll] (first (first coll)))
|
|
(defn nfirst [coll] (next (first coll)))
|
|
(defn fnext [coll] (first (next coll)))
|
|
(defn nnext [coll] (next (next coll)))
|
|
|
|
;; Canonical Clojure defs: pure first/next/loop/recur, no Janet realize-for-iteration.
|
|
(defn last [s]
|
|
(if (next s) (recur (next s)) (first s)))
|
|
|
|
(defn butlast [s]
|
|
(loop [ret [] s s]
|
|
(if (next s)
|
|
(recur (conj ret (first s)) (next s))
|
|
(seq ret))))
|
|
|
|
(defn- mapcat-step [rs cur]
|
|
(lazy-seq
|
|
(if cur
|
|
(let [s (seq cur)]
|
|
(if s
|
|
(cons (first s) (mapcat-step rs (rest s)))
|
|
(mapcat-step rs nil)))
|
|
(let [s (seq rs)]
|
|
(if s
|
|
(let [c (first s)
|
|
sc (seq c)]
|
|
(if sc
|
|
(cons (first sc) (mapcat-step (rest s) (rest sc)))
|
|
(mapcat-step (rest s) nil)))
|
|
nil)))))
|
|
|
|
(defn mapcat
|
|
([f] (comp (map f) cat))
|
|
([f coll]
|
|
(mapcat-step (map f coll) nil))
|
|
([f c1 c2]
|
|
(mapcat-step (map f c1 c2) nil))
|
|
([f c1 c2 c3]
|
|
(mapcat-step (map f c1 c2 c3) nil))
|
|
([f c1 c2 c3 & colls]
|
|
(mapcat-step (apply map f c1 c2 c3 colls) nil)))
|