This章节说明actual-value
用于提取thunk实际值的定义是这样的:
(define (actual-value exp env)
(force-it (eval exp env)))
但是,如果exp
本身就是一个笨蛋怎么办?根据{{1}}的定义,它意味着它是delay-it
形式的列表对象。然而,eval函数无法准备处理以'thunk开头的标记列表。为什么eval不会因为cond表达式无法匹配而产生错误?
修改 我认为评估以下表达式会导致错误:
(list 'thunk exp env)
(define (add a) (+ 2 a))
(add 0)
是一个复合过程,因此在应用它之前会对其参数执行add
。 delay-it
是原始产品,这意味着将在其参数上调用+
。参数是2和a。 a是一个thunk对象,因此actual-value
在将其传递给actual-value
时会产生错误,因为eval
没有cond情况处理标记为'thunk的列表。
答案 0 :(得分:3)
这里的关键点是,当我们评估(+ 2 a)
a
不是thunk时,它只是一个将在环境中查找的符号,其值为thunk。在eval
返回thunk之后,force-it
将负责强制其值。让我们逐步完成整个过程。
在您的示例中,唯一的参数是0
,在调用add
时,但即使这样,该值也会被强制最终 {{ 1}} - 想一想,在某些时候,所有的程序应用程序都会导致list-of-arg-values
,这就是我们强迫thunk的重点。
如果我们在调用apply-primitive-procedure
时执行跟踪,则传递给list-of-arg-values
的值按此顺序为actual-value
和2
。 a
只评估自己,没问题。让我们看看2
会发生什么。 a
中的这个代码段:
actual-value
...将收到符号(eval exp env)
作为其a
(变量),在环境中查找后返回相关的thunk(请记住:当我们在{{1}扩展环境时我们在变量和thunk之间创建了绑定),之后exp
会因调用apply
而收到thunk:
force-it
在eval
案例中, ... (force-it (eval exp env)))
知道如何评估thunk。就是这样!最后我们获得force-it
,即实际值。