Stream Scheme:使用'delay'表达式时的显示问题
这是一个与SICP中的ex3.51相关的问题,下面是代码Stream Scheme:使用'delay'表达式时的显示问题,stream,scheme,delay,sicp,Stream,Scheme,Delay,Sicp,这是一个与SICP中的ex3.51相关的问题,下面是代码 (define (cons-stream x y) (cons x (delay y))) (define (stream-car stream) (car stream)) (define (stream-cdr stream) (force (cdr stream))) (define (stream-map proc s) (if (stream-null? s) the-empty-stream (
(define (cons-stream x y)
(cons x (delay y)))
(define (stream-car stream) (car stream))
(define (stream-cdr stream) (force (cdr stream)))
(define (stream-map proc s)
(if (stream-null? s)
the-empty-stream
(cons-stream
(proc (stream-car s))
(stream-map proc (stream-cdr s)))))
(define (stream-enumerate-interval low high)
(if (> low high)
the-empty-stream
(cons-stream
low
(stream-enumerate-interval (+ low 1) high))))
(define (stream-ref s n)
(if (= n 0)
(stream-car s)
(stream-ref (stream-cdr s) (- n 1))))
(define (show x)
(display x)
x)
;test
(stream-map show (stream-enumerate-interval 0 10))
输出为012345678910(0.#)
但是我认为
cons stream
中的延迟表达式延迟了计算,如果我在stream map
中使用不同的处理函数,比如lambda(x)(+x1)
输出(1.#)
更合理,那么为什么显示
打印所有数字呢 这个定义的问题在于:
(define (cons-stream x y)
(cons x (delay y)))
它将cons-stream
定义为一个函数,因为它使用define
Scheme的求值是急切的:在输入函数体之前对参数求值。因此,当将y
传递到delay
时,已经完全计算了它
相反,cons-stream
应该定义为宏,如
(define-syntax cons-stream
(syntax-rules ()
((_ a b) (cons a (delay b)))))
或者我们可以显式地、手动地调用delay
,例如
(define (stream-map proc s)
(if (stream-null? s)
the-empty-stream
(cons
(proc (stream-car s))
(delay
(stream-map proc (stream-cdr s))))))
那么在我们的代码中就不会有对cons stream
的调用,只有(cons A(delay B))
调用。而delay
是一个宏(或特殊形式,无论什么),它在工作之前不计算参数,而是直接操作参数表达式
我们甚至可以放弃对delay
的调用,将(cons A(delay B))
替换为(cons A(lambda()B))
。这还需要将force
(它是内置的,与内置的延迟一起)重新实现为简单的(定义(force x)(x))
,或者在适当的情况下手动调用(x)
,以强制流的尾部
您可以在末尾看到基于lambda的流代码,或者使用显式lambda而不使用任何宏的(for)。这种方法可以改变代码的性能,因为delay
正在进行记忆,但基于lambda
的流不会。如果我们尝试多次访问流的元素,就会看到不同之处
另请参见另一个关于streams实现的介绍,通过手术将列表的最后一个cons单元格修改为memonizingforce
将其放在本书的上下文中,“渴望”评估就是本书所称的应用程序顺序。您在原始定义中遇到的问题在第3.5.1节的脚注56中进行了说明-目前我们还没有实现我们自己的cons流的工具,但这将在第4.1节中进行说明,在第4.1节中,我们了解了更多关于特殊表单的信息,在第4.2节中,我们实现了必要的正常顺序(惰性)评估。谢谢,但是(cons..delay)本质上与(cons stream…)相同,对吗?如果在传递到delay时已经计算了y,那么如果传递lambda(x)(+x1),为什么输出是(1.#)而不是1234567891011要流映射吗?不,如果我们以这种方式手动写出来,就没有y
。没有函数调用,只有嵌套的表达式,delay
中的表达式确实会延迟。因此,如果我们以这种方式做,代码中就不会有任何对cons-stream
的调用,只需调用cons
和delay
与(cons A(delay B))
一样,delay
是一个宏(或一种特殊形式,无论什么),它在工作之前不计算参数,而是直接操作参数表达式。