在此代码段中:
(begin
(define f '())
((lambda ()
(set! f (lambda (x) (g x 5)))))
(define (g x y) (+ x y))
(f 5))
当(set! f (lambda...))
被评估时,变量 g 不绑定到任何位置。正如 R5RS 的规范(链接在这里)所说:
计算 lambda 表达式时生效的环境将作为过程的一部分被记住。当稍后使用一些实际参数调用过程时,将通过将形式参数列表中的变量绑定到新位置来扩展评估 lambda 表达式的环境,相应的实际参数值将存储在这些位置,并且lambda 表达式主体中的表达式将在扩展环境中按顺序计算。
其中“有效环境”在某一时刻被定义为:
命名位置的标识符称为变量,并且被称为绑定到该位置。在程序中某个点生效的所有可见绑定的集合称为该点生效的环境。
所以内部 lambda 应该只捕获像这样的环境{f: (location #1)}
;并且当通过调用(f 5)
用于评估其主体的环境来评估它时,它应该是{f: (location #1), x: (location #2)}
不包含g
.
但是 DrRacket(还有 petite,它是一个 R6RS 实现)在评估上述代码段时给出了 10。所以环境确实包含g
. 为什么?
=====
似乎该方案要求定义语句仅出现在<body>
. 但此代码段也返回 10:
(begin
(define (f x) (g x 5))
(define (g x y) (+ x y))
(f 5))