首页 文章

词汇范围和共享对象

提问于
浏览
1

考虑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)

脚注:

通过多个名称访问单个计算对象的现象称为别名 . 联合银行账户情况说明了一个非常简单的别名示例 . ...如果我们忘记对对象的更改也可能发生错误,作为“副作用”,更改“不同”对象,因为两个“不同”对象实际上是出现在不同别名下的单个对象 . 这些所谓的副作用错误很难定位和分析,有些人提出编程语言的设计方式是不允许副作用或别名......“

在正常情况下,我会在这里说:“paul-acc指的是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指向全局环境 .
    评估

  • (定义peter-acc( 生产环境 账户100)) . make-account创建一个新的环境e1 . 封闭的环境是全球性的 . 内部程序撤销,存入和发送都已创建,并指向e1 . 返回Dispatch并绑定到全局环境中的名称peter-acc .
    评估

  • (定义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-acount都指向e1中的调度程序 .

  • 身体被执行 .

这都是正确的吗?

令我困惑的是当我在SICP练习中遇到这样的事情时,在构建环境图时,我会在网上看到人们说“银行账户是指保罗 - 保罗 . 保罗 - acc指的是peter-acc . ”为什么这里使用“引用”一词到底是什么?关于e2的银行账户实际上是否指向paul-acc这个名称,而不是它的 Value ?

1 回答

  • 1

    你的第2点到第5点是正确的 . 在你的观点1中, fmake-account 并没有指向全球环境 - 它们本身并不需要它们 . 它们都是全局环境中的条目,绑定 . 在这两种情况下,"refer to"或"point at"简单值都起作用 .

    bank-account 关于 e2 实际上指向 paul-acc 指向的值(与 peter-acc 指向或指的是相同的值) . 在Scheme中, (define n1 n2) 表示“在当前环境中设置新绑定,名为 n1 ,并指向表达式 n2 的值” . 如果 n2 恰好是变量,则其值就是该变量的值 . 那个's why we'谈论的是Scheme的评估语义 .

    函数调用 (fun arg) 通过查找 arg 表达式的值,将函数的参数绑定到此值,然后在结果环境中评估函数的主体来计算:

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

相关问题