Chez Phase 2 (inc G): lazy-seq bridge (make-lazy-seq / coll->cells)
The lazy-seq macro expands to (make-lazy-seq (fn* [] (coll->cells body))) and lazy-cat to (concat (lazy-seq c) ...); both seed natives were nil on the prelude, so every overlay fn built on lazy-seq — repeat/iterate/ cycle/dedupe/take-nth/keep/interpose/reductions/map-indexed/distinct/ interleave/tree-seq(->flatten)/partition-all/lazy-cat — hit apply-jolt-nil. lazy-bridge.ss bridges to the cseq model: a jolt-lazyseq is a deferred seq forced once by an extended jolt-seq; jolt-cons defers a lazyseq tail so an infinite (repeat/iterate/cycle) stays lazy. A lazyseq is a new value type, so the dispatchers that don't route through jolt-seq learn it (sequential? for =/hash, plus count/empty?/nth/printers) or a raw unrealized lazyseq escapes — the corpus compares (= [1 3 5] (take-nth …)) against it directly. seq.ss: jolt-concat is now fully lazy (the rest isn't forced until the first coll is exhausted), so a self-referential lazy-cat — fib = (lazy-cat [0 1] (map + (rest fib) fib)) — no longer memoizes its tail as empty by reading fib before its def binds. Prelude parity 1837 -> 1886, 0 new divergences. Floor raised to 1886.
This commit is contained in:
parent
241095977f
commit
e434a7d352
4 changed files with 100 additions and 7 deletions
|
|
@ -176,15 +176,18 @@
|
|||
(if (or (fx<=? n 0) (jolt-nil? s)) (if (jolt-nil? s) jolt-empty-list s)
|
||||
(loop (fx- n 1) (jolt-seq (seq-more s))))))
|
||||
|
||||
(define (concat2 a b) ; lazily append seq a then seqable b
|
||||
(if (jolt-nil? a) (jolt-seq b)
|
||||
(cseq-lazy (seq-first a) (lambda () (concat2 (jolt-seq (seq-more a)) b)))))
|
||||
;; lazily append seq a then the seqable produced by the thunk `brest` — the rest
|
||||
;; is NOT forced until a is exhausted, so concat is fully lazy (Clojure semantics).
|
||||
;; This matters for a self-referential lazy-cat (fib = (lazy-cat [0 1] (map + (rest
|
||||
;; fib) fib))): forcing the rest eagerly at construction would read fib before its
|
||||
;; def binds, memoizing the tail as empty.
|
||||
(define (concat2 a brest)
|
||||
(if (jolt-nil? a) (jolt-seq (brest))
|
||||
(cseq-lazy (seq-first a) (lambda () (concat2 (jolt-seq (seq-more a)) brest)))))
|
||||
(define (jolt-concat . colls)
|
||||
(cond ((null? colls) jolt-empty-list)
|
||||
((null? (cdr colls)) (jolt-seq (car colls)))
|
||||
(else (let loop ((c (jolt-seq (car colls))) (rest (cdr colls)))
|
||||
(if (null? rest) (if (jolt-nil? c) jolt-empty-list c)
|
||||
(concat2 c (apply jolt-concat rest)))))))
|
||||
(else (concat2 (jolt-seq (car colls)) (lambda () (apply jolt-concat (cdr colls)))))))
|
||||
|
||||
;; (apply f a b ... coll): spread the trailing seqable into the call.
|
||||
(define (jolt-apply f . args)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue