词法作用域和共享对象
Lexical Scoping and sharing objects
考虑 SICP 中的记帐程序。
(define (make-account balance)
(define (withdraw amount)
(if (>= balance amount)
(begin
(set! balance (- balance amount))
balance)
"Insufficient funds"))
(define (deposit amount)
(set! balance (+ balance amount))
balance)
(define (dispatch m)
(cond ((eq? m 'withdraw) withdraw)
((eq? m 'deposit) deposit)
(else (error "Unknown request: MAKE-ACCOUNT" m))))
dispatch)
以及示例:
(define peter-acc (make-account 100))
(define paul-acc peter-acc)
以及脚注:
The phenomenon of a single computational object being accessed by more
than one name is known as aliasing. The joint bank account situation
illustrates a very simple example of an alias.
...
Bugs can
occur in our programs if we forget that a change to an object may
also, as a “side effect,” change a “different” object because the two
“different” objects are actually a single object appearing under
different aliases. These so-called side-effect bugs are so difficult
to locate and to analyze that some people have proposed that
programming languages be designed in such a way as to not allow side
effects or aliasing
..."
在正常情况下,我会在这里的人说:"paul-acc refers to peter-acc"。
据我了解,peter-acc 和paul-acc 确实是指向一个计算对象的名称。所以他们是一样的。
我对如何在评估环境模型中建模感到困惑。例如:
(define (f bank-account) ((bank-account 'deposit) 69))
(define peter-acc (make-account 100))
(define paul-acc peter-acc)
(f paul-acc)
我不能做环境图,因为我的眼睛坏了。这是我认为互动应该是的:
- make-account 和 f 有指向全局环境的指针。
- (define peter-acc (make-account 100)) 被评估。 make-account 创建一个新环境 e1。封闭环境是全球性的。内部过程 withdraw、deposit 和 dispatch 被创建并具有指向 e1 的指针。 Dispatch 返回并绑定到全局环境中的名称 peter-acc。
- (define paul-acc peter-acc) 被评估。名称 peter-acc 在全局框架中找到。 paul-acc 绑定到 e1 中的调度过程对象,因为那是 peter-acc 指向的地方。因此e1中的Dispatch绑定了全局环境中的名字peter-acc和paul-acc
- (f paul-acc) 被评估。 f创建了一个新环境e2。封闭环境是全球性的。 paul-acc 在全球范围内找到。在 e2 中,banck-account 绑定到 e1 中的调度过程对象,因为那是 paul-acc 指向的地方。所以全局环境的peter-acc,全局环境的paul-acc,e2的bank-account都指向e1中的dispatch流程
- 尸体被处决。
这一切都正确吗?
让我感到困惑的是,当我在 SICP 练习中遇到这样的事情时,在构建环境图时,我在网上看到有人说 "bank-account refers to paul-acc. Paul-acc refers to peter-acc." 为什么这个词 "refers"用在这里?关于 e2 的银行账户是否实际指向名称 paul-acc 而不是它的值?
您的第 2 点到第 5 点是正确的。在您的第 1 点中,f
和 make-account
不 "have" 指向全局环境的指针 - 它们本身不需要。它们都是条目,绑定,在全局环境中。 "refer to" 或 "point at" 简单值在这两种情况下都有效。
bank-account
相对于 e2
实际上指向 值 paul-acc
指向(与 peter-acc
分,或指)。在 Scheme 中,(define n1 n2)
表示 "set up new binding in the current environment, named n1
, and pointing at the value of the expression n2
"。如果 n2
恰好是一个变量,它的值就是该变量的值 是 。这就是我们谈论 Scheme 的 evaluation 语义的原因。
函数调用 (fun arg)
通过查找 arg
expression 的 value 来求值,绑定函数的此 value 的参数,然后在生成的环境中评估函数的主体:
( (lambda (param) body) arg )
=
(let ( (param arg) )
body)
考虑 SICP 中的记帐程序。
(define (make-account balance)
(define (withdraw amount)
(if (>= balance amount)
(begin
(set! balance (- balance amount))
balance)
"Insufficient funds"))
(define (deposit amount)
(set! balance (+ balance amount))
balance)
(define (dispatch m)
(cond ((eq? m 'withdraw) withdraw)
((eq? m 'deposit) deposit)
(else (error "Unknown request: MAKE-ACCOUNT" m))))
dispatch)
以及示例:
(define peter-acc (make-account 100))
(define paul-acc peter-acc)
以及脚注:
The phenomenon of a single computational object being accessed by more than one name is known as aliasing. The joint bank account situation illustrates a very simple example of an alias.
...
Bugs can occur in our programs if we forget that a change to an object may also, as a “side effect,” change a “different” object because the two “different” objects are actually a single object appearing under different aliases. These so-called side-effect bugs are so difficult to locate and to analyze that some people have proposed that programming languages be designed in such a way as to not allow side effects or aliasing
..."
在正常情况下,我会在这里的人说:"paul-acc refers to peter-acc"。
据我了解,peter-acc 和paul-acc 确实是指向一个计算对象的名称。所以他们是一样的。
我对如何在评估环境模型中建模感到困惑。例如:
(define (f bank-account) ((bank-account 'deposit) 69))
(define peter-acc (make-account 100))
(define paul-acc peter-acc)
(f paul-acc)
我不能做环境图,因为我的眼睛坏了。这是我认为互动应该是的:
- make-account 和 f 有指向全局环境的指针。
- (define peter-acc (make-account 100)) 被评估。 make-account 创建一个新环境 e1。封闭环境是全球性的。内部过程 withdraw、deposit 和 dispatch 被创建并具有指向 e1 的指针。 Dispatch 返回并绑定到全局环境中的名称 peter-acc。
- (define paul-acc peter-acc) 被评估。名称 peter-acc 在全局框架中找到。 paul-acc 绑定到 e1 中的调度过程对象,因为那是 peter-acc 指向的地方。因此e1中的Dispatch绑定了全局环境中的名字peter-acc和paul-acc
- (f paul-acc) 被评估。 f创建了一个新环境e2。封闭环境是全球性的。 paul-acc 在全球范围内找到。在 e2 中,banck-account 绑定到 e1 中的调度过程对象,因为那是 paul-acc 指向的地方。所以全局环境的peter-acc,全局环境的paul-acc,e2的bank-account都指向e1中的dispatch流程
- 尸体被处决。
这一切都正确吗?
让我感到困惑的是,当我在 SICP 练习中遇到这样的事情时,在构建环境图时,我在网上看到有人说 "bank-account refers to paul-acc. Paul-acc refers to peter-acc." 为什么这个词 "refers"用在这里?关于 e2 的银行账户是否实际指向名称 paul-acc 而不是它的值?
您的第 2 点到第 5 点是正确的。在您的第 1 点中,f
和 make-account
不 "have" 指向全局环境的指针 - 它们本身不需要。它们都是条目,绑定,在全局环境中。 "refer to" 或 "point at" 简单值在这两种情况下都有效。
bank-account
相对于 e2
实际上指向 值 paul-acc
指向(与 peter-acc
分,或指)。在 Scheme 中,(define n1 n2)
表示 "set up new binding in the current environment, named n1
, and pointing at the value of the expression n2
"。如果 n2
恰好是一个变量,它的值就是该变量的值 是 。这就是我们谈论 Scheme 的 evaluation 语义的原因。
函数调用 (fun arg)
通过查找 arg
expression 的 value 来求值,绑定函数的此 value 的参数,然后在生成的环境中评估函数的主体:
( (lambda (param) body) arg )
=
(let ( (param arg) )
body)