lambda 中的标识符何时绑定?
When is a identifier in a lambda bound?
我正在读SICP。有些事情让我感到困惑。这些都是我自己写的,测试一下
;This procedure bind a symbol `f` to a lambda, and that lambda is not evaluated.
(define f
(lambda () x))
;create a frame which binds x to 10, and then evaluate f, should return 10.
(let ((x 10))
(f))
但是DrRacket不接受
x: unbound identifier in module in: x
方案有词法范围。这意味着当计算 lambda 的主体时,它是使用创建 lambda 的环境而不是调用它的环境来计算的。
因此,虽然在调用 f
时存在 x
变量,但这并不重要,因为 Scheme 在您定义 [=11] 的环境中查找 x
的定义=] 其中不存在这样的变量。
您在这里看到的问题是 x
是一个自由变量。 Racket(和大多数语言)中的表达式不能有自由变量(称为 "closed term")[2].
如果您有自由变量,如示例中的 x
,则需要在绑定了 x
的某些事件的环境中调用该函数。您可以通过在绑定 x
.
的 let
中调用它来实现这一点
但是,Scheme 是词法范围的[1],这意味着它从定义它的环境中捕获变量。但是您没有在定义 lambda 的范围内定义 x
。因此错误。
一些阅读以启发这一点:
[1] 静态与词法范围:Static (Lexical) Scoping vs Dynamic Scoping (Pseudocode)
[2] 自由变量:https://en.wikipedia.org/wiki/Free_variables_and_bound_variables
这是因为词法范围。
(define f
(lambda () x))
由于 x
不在词法范围内,因此 必须是全局变量 。因此,您可以执行以下操作:
(define x 10)
(f) ;=> 10
要使其成为词法变量,它必须在创建时已经存在:
(define f
(let ((x 10))
(lambda () x)))
在这个例子中,由于 x
是一个绑定词法变量,因此 lambda 中的 x
是相同的,因为 lambda 继承了它被评估的环境.
是的! lambda
表达式 被评估 以便它成为过程对象并且 define
将全局符号 f
分配给该对象。
证明尝试应用列表结构:
('(lambda (x) x) 10) ; gets error 'application: not a procedure'
在具有动态作用域的 LISP 中,过程没有环境,环境是在调用时从运行时获取的:
(define (test)
some-value)
(define (call-test)
(let ((some-value 10))
(test))) ; => 10
(test) ; => error (unbound variable)
正如您在动态作用域中看到的那样,很难判断过程是否正确,因为每次调用时它所处的环境都会发生变化。编译器优化词法范围也容易得多。
我正在读SICP。有些事情让我感到困惑。这些都是我自己写的,测试一下
;This procedure bind a symbol `f` to a lambda, and that lambda is not evaluated.
(define f
(lambda () x))
;create a frame which binds x to 10, and then evaluate f, should return 10.
(let ((x 10))
(f))
但是DrRacket不接受
x: unbound identifier in module in: x
方案有词法范围。这意味着当计算 lambda 的主体时,它是使用创建 lambda 的环境而不是调用它的环境来计算的。
因此,虽然在调用 f
时存在 x
变量,但这并不重要,因为 Scheme 在您定义 [=11] 的环境中查找 x
的定义=] 其中不存在这样的变量。
您在这里看到的问题是 x
是一个自由变量。 Racket(和大多数语言)中的表达式不能有自由变量(称为 "closed term")[2].
如果您有自由变量,如示例中的 x
,则需要在绑定了 x
的某些事件的环境中调用该函数。您可以通过在绑定 x
.
let
中调用它来实现这一点
但是,Scheme 是词法范围的[1],这意味着它从定义它的环境中捕获变量。但是您没有在定义 lambda 的范围内定义 x
。因此错误。
一些阅读以启发这一点:
[1] 静态与词法范围:Static (Lexical) Scoping vs Dynamic Scoping (Pseudocode)
[2] 自由变量:https://en.wikipedia.org/wiki/Free_variables_and_bound_variables
这是因为词法范围。
(define f
(lambda () x))
由于 x
不在词法范围内,因此 必须是全局变量 。因此,您可以执行以下操作:
(define x 10)
(f) ;=> 10
要使其成为词法变量,它必须在创建时已经存在:
(define f
(let ((x 10))
(lambda () x)))
在这个例子中,由于 x
是一个绑定词法变量,因此 lambda 中的 x
是相同的,因为 lambda 继承了它被评估的环境.
是的! lambda
表达式 被评估 以便它成为过程对象并且 define
将全局符号 f
分配给该对象。
证明尝试应用列表结构:
('(lambda (x) x) 10) ; gets error 'application: not a procedure'
在具有动态作用域的 LISP 中,过程没有环境,环境是在调用时从运行时获取的:
(define (test)
some-value)
(define (call-test)
(let ((some-value 10))
(test))) ; => 10
(test) ; => error (unbound variable)
正如您在动态作用域中看到的那样,很难判断过程是否正确,因为每次调用时它所处的环境都会发生变化。编译器优化词法范围也容易得多。