词法作用域和共享对象

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)

我不能做环境图,因为我的眼睛坏了。这是我认为互动应该是的:

这一切都正确吗?

让我感到困惑的是,当我在 SICP 练习中遇到这样的事情时,在构建环境图时,我在网上看到有人说 "bank-account refers to paul-acc. Paul-acc refers to peter-acc." 为什么这个词 "refers"用在这里?关于 e2 的银行账户是否实际指向名称 paul-acc 而不是它的值?

您的第 2 点到第 5 点是正确的。在您的第 1 点中,fmake-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 expressionvalue 来求值,绑定函数的此 value 的参数,然后在生成的环境中评估函数的主体:

( (lambda (param) body) arg )
=
(let ( (param arg) )
   body)