Stream Scheme:使用'delay'表达式时的显示问题

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 (

这是一个与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
      (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单元格修改为memonizing
force

将其放在本书的上下文中,“渴望”评估就是本书所称的应用程序顺序。您在原始定义中遇到的问题在第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
是一个宏(或一种特殊形式,无论什么),它在工作之前不计算参数,而是直接操作参数表达式。