是否将非功能重新分配为带有 set! 的功能?创建一个新框架?
Does re-assigning a non-function to be a function with set! create a new frame?
下面的代码让我很困惑:
(define (even-or-odd-letrec x)
((lambda (internal-even? internal-odd?)
(set! internal-even? (lambda (n)
(if (= n 0) 'even
(internal-odd? (- n 1)))))
(set! internal-odd? (lambda (n)
(if (= n 0) 'odd
(internal-even? (- n 1)))))
(internal-even? x))
#f #f))
我看的环境如下:
- 在
even-or-odd-letrec
的环境中,internal-even?
和 internal-odd?
最初绑定到 #f
。他们的父环境是全局环境。
set!
然后将这两个值更改为明显的 lambda
s,但不会更改环境。
- 因为环境没有改变,所以对
internal-even?
的任何调用都将在全局环境中查找 internal-odd?
,但一无所获。
那么这段代码是如何工作的?
回答您的问题标题:不,设置不会创建任何新框架。
Setting 设置当前环境框架中绑定的值。无论旧值和新值是什么。功能与否,没有区别。
同样,set!
不会更改值。它会更改 bindings' 值。绑定是名称及其值的配对。 Set!
ting 更改该名称的绑定值。
被视为命名指针,在重新set!
之后,名称指向一个新值——该值作为第二个参数提供给set!
。
所以与你所说的相反,set!
确实 改变了 当前的环境框架——它改变了它对给定名称集的绑定。
+---------------+ +---------------+
| n1 ---> v1 | | n1 ---> x |
| n2 ---> v2 | (set! n1 x) | n2 ---> v2 |
|---------------| -------------> |---------------|
| ..code... | | ..code... |
|_______________| |_______________|
“任何对 internal-even?
的调用都会”......停止!这不是正确的看待方式。
在 lambda
创建的框架内对 internal-even?
的任何引用都将通过在同一框架中查找名称 internal-even?
下的值来解决,一切都会正常进行.
当你 (set! internal-even? (lambda (...) ... internal-odd? ...))
时,确实 internal-odd?
的 值 仍然不是它应该的,但这没关系,因为它还没有查找值——因为 internal-even?
还不是 运行。当一个 lambda 表达式被求值时(这里,作为 set!
调用的一部分),它的值是这样的函数:时间到了,当这个函数 运行s,然后根据需要在其中查找任何名称的值.
当应用于两个参数值时,(lambda (internal-even? internal-odd?) ...)
会创建一个新环境,其中包含 internal-even?
和 internal-odd?
的绑定。该环境中引用 internal-even?
或 internal-odd?
的任何内容都将引用代码运行时这些绑定的当前值。 set!
通过改变绑定的值来改变这个环境,这样这些绑定的当前值现在是两个过程,它们本身引用这些绑定的当前值。
我认为,到目前为止,理解这一点的最简单方法是实现一个小解释器。做到这一点非常容易:您将 alists 用于环境,评估器几乎需要处理 if
和 lambda
以及 set!
作为特殊情况。每个人都应该写一篇。
设置变量不会绑定新位置。但是请注意,绑定一个新变量并不意味着 create/enlarge 一个框架。如果您可以证明变量的行为,可以将变量保存在寄存器中而不是帧中(就像在 C 中一样),或者根本不保存它们。
下面的代码让我很困惑:
(define (even-or-odd-letrec x)
((lambda (internal-even? internal-odd?)
(set! internal-even? (lambda (n)
(if (= n 0) 'even
(internal-odd? (- n 1)))))
(set! internal-odd? (lambda (n)
(if (= n 0) 'odd
(internal-even? (- n 1)))))
(internal-even? x))
#f #f))
我看的环境如下:
- 在
even-or-odd-letrec
的环境中,internal-even?
和internal-odd?
最初绑定到#f
。他们的父环境是全局环境。 set!
然后将这两个值更改为明显的lambda
s,但不会更改环境。- 因为环境没有改变,所以对
internal-even?
的任何调用都将在全局环境中查找internal-odd?
,但一无所获。
那么这段代码是如何工作的?
回答您的问题标题:不,设置不会创建任何新框架。
Setting 设置当前环境框架中绑定的值。无论旧值和新值是什么。功能与否,没有区别。
同样,set!
不会更改值。它会更改 bindings' 值。绑定是名称及其值的配对。 Set!
ting 更改该名称的绑定值。
被视为命名指针,在重新set!
之后,名称指向一个新值——该值作为第二个参数提供给set!
。
所以与你所说的相反,set!
确实 改变了 当前的环境框架——它改变了它对给定名称集的绑定。
+---------------+ +---------------+
| n1 ---> v1 | | n1 ---> x |
| n2 ---> v2 | (set! n1 x) | n2 ---> v2 |
|---------------| -------------> |---------------|
| ..code... | | ..code... |
|_______________| |_______________|
“任何对 internal-even?
的调用都会”......停止!这不是正确的看待方式。
在 lambda
创建的框架内对 internal-even?
的任何引用都将通过在同一框架中查找名称 internal-even?
下的值来解决,一切都会正常进行.
当你 (set! internal-even? (lambda (...) ... internal-odd? ...))
时,确实 internal-odd?
的 值 仍然不是它应该的,但这没关系,因为它还没有查找值——因为 internal-even?
还不是 运行。当一个 lambda 表达式被求值时(这里,作为 set!
调用的一部分),它的值是这样的函数:时间到了,当这个函数 运行s,然后根据需要在其中查找任何名称的值.
当应用于两个参数值时,(lambda (internal-even? internal-odd?) ...)
会创建一个新环境,其中包含 internal-even?
和 internal-odd?
的绑定。该环境中引用 internal-even?
或 internal-odd?
的任何内容都将引用代码运行时这些绑定的当前值。 set!
通过改变绑定的值来改变这个环境,这样这些绑定的当前值现在是两个过程,它们本身引用这些绑定的当前值。
我认为,到目前为止,理解这一点的最简单方法是实现一个小解释器。做到这一点非常容易:您将 alists 用于环境,评估器几乎需要处理 if
和 lambda
以及 set!
作为特殊情况。每个人都应该写一篇。
设置变量不会绑定新位置。但是请注意,绑定一个新变量并不意味着 create/enlarge 一个框架。如果您可以证明变量的行为,可以将变量保存在寄存器中而不是帧中(就像在 C 中一样),或者根本不保存它们。