我目前正在通过 SICP 进行工作,使用 Guile 作为我的主要练习语言。在实现第 3.5 章中的练习时,我发现了一个奇怪的行为。我已经在各种平台上使用 Guile 1.4、Guile 1.8.6 和 Guile 1.8.7 重现了此行为,并且确信它不是特定于我的设置。
这段代码工作正常(并计算 e):
(define y (integral (delay dy) 1 0.001))
(define dy (stream-map (lambda (x) x) y))
(stream-ref y 1000)
以下代码应该给出相同的结果:
(define (solve f y0 dt)
(define y (integral (delay dy) y0 dt))
(define dy (stream-map f y))
y)
(stream-ref (solve (lambda (x) x) 1 0.001) 1000)
但它会产生错误消息:
standard input:7:14: While evaluating arguments to stream-map in expression (stream-map f y):
standard input:7:14: Unbound variable:
y ABORT: (unbound-variable)
因此,当嵌入过程定义中时, (define y ...) 不起作用,而在 REPL 的全局环境中的过程之外,它可以正常工作。
我在这里做错了什么?如果有必要,我也可以发布辅助代码(即积分、流映射等的定义)。除了 cons-stream 的系统相关代码之外,它们都在书中。我自己的 Guile cons-stream 实现如下:
(define-macro (cons-stream a b)
`(cons ,a (delay ,b)))
最佳答案
您不能拥有相互依赖的内部 DEFINE;语言规范明确指出了这一点(R5RS 5.2.2):
... it must be possible to evaluate each expression of every internal definition in a body without assigning or referring to the value of any variable being defined.
您可以将其视为解释器正在收集所有定义并在正文之前以随机顺序评估它们。由于顺序是随机的,因此如果您希望它能够正常工作,就不会存在任何相互依赖性。
SOLVE 定义 (#71) 中甚至还附加了一个脚注,表明它并不适用于所有方案。
您必须编写代码,以便一个定义非常清楚地位于另一个定义的范围内,就像嵌套的 LET 一样:
(define (solve f y0 dt) (let ((y (integral (delay dy) y0 dt))) (let ((dy (stream-map f y))) y)))
关于scheme - 方案中循环定义的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2828996/