我想在Scheme中制作一个懒惰的列表。这是我到目前为止所做的。
;; Constructor for Pairs
(define (cons-stream a b)
(cons a (λ() b)))
;; Selectors
(define (car-stream a-stream)
(car a-stream))
(define (cdr-stream a-stream)
((cdr a-stream)))
;; Lazy List using the pairs
(define (lazy-list from)
(cons-stream from (lazy-list (+ from 1))))
;; Take function
(define (take a-lazy-list number)
(define (take-helper i )
(if(= i number)
empty
(cons (car a-lazy-list) (take-helper (+ i 1)))))
(take-helper 0))
lazy-list的问题是Scheme首先计算内部表达式(lazy-list(+ from 1)),导致过程进入无限递归。
有没有办法让con-stream在没有任何评估的情况下接受这个内部表达?
答案 0 :(得分:3)
解决方案是使用宏。我不是计划专家(尤其不是宏),但也许这个片段可以作为灵感:
(define-syntax pointer-to
(syntax-rules ()
((pointer-to var)
(make-pointer
(lambda () var) ; the "pointer dereference" operation
(lambda (value) (set! var value)))))) ; "pointer write"
使用如下:
(define x 1)
(define px (pointer-to x))
(pointer-set! px 2) ; this (in some sense) becomes `(set! x 2)'
所以也许你想要像
这样的东西(define-syntax lazy-cons
(syntax-rules ()
((lazy-cons head lazytail)
(cons head (lambda () lazytail)))))
但我不确定。看看define-syntax
。
答案 1 :(得分:3)
如果你不想走宏观路线,你可以随时放弃cons-stream
并重写lazy-list
,如下所示:
(define (lazy-list from)
(cons from (λ() (lazy-list (+ from 1)))))
这可能是最简单,最实用的解决方案,但它只适用于生成递增数字的惰性列表。您可以通过传入一个函数来概括它,该函数在调用时将生成列表的连续元素:
(define (lazy-list-gen generator)
(cons (generator)
(λ() (lazy-list-gen generator))))
(define (lazy-list from)
(lazy-list-gen
(λ()
(let ((ret from))
(set! from (+ from 1))
ret))))
这非常有效:
> (define x (lazy-list 1))
> (car-stream x)
1
> (car-stream (cdr-stream x))
2
但是代码中有一个错误:
... continuing from above ...
> (car-stream (cdr-stream x))
3
发生此错误是因为cdr-stream
的来电再次呼叫generator
。我们可以通过缓存lambda的返回值来解决这个问题:
(define (lazy-list-gen generator)
(cons (generator)
(let ((gen-cache #f))
(λ()
(cond ((not gen-cache)
(set! gen-cache (lazy-list-gen generator))))
gen-cache))))
现在它可以正常工作:
> (define x (lazy-list 1))
> (car-stream x)
1
> (car-stream (cdr-stream x))
2
> (car-stream (cdr-stream x))
2
> (car-stream (cdr-stream (cdr-stream x)))
3
> (car-stream (cdr-stream x))
2
答案 2 :(得分:2)
Scheme中的惰性列表称为流。 Here's the standard introduction.
答案 3 :(得分:1)