词汇范围和共享对象

时间:2018-04-14 14:21:27

标签: reference scheme lisp sicp lexical-scope

考虑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练习中遇到这样的事情时,在构建环境图时,我会在网上看到人们说像银行账户这样的东西是指paul-acc。 Paul-acc指的是peter-acc。"为什么单词"指的是"用在这里?关于e2的银行账户是否实际上指的是名称paul-acc而不是它的价值?

1 个答案:

答案 0 :(得分:1)

你的第2点到第5点是正确的。在您的第1点,fmake-account没有"有"指向全球环境的指针 - 它们本身并不需要。它们都是条目,绑定, in 全局环境。两个"指的是",或者"指向"简单的值,两种情况下的功能。

关于bank-account

e2实际上指向paul-acc点的(与peter-acc点相同的值,或参考)。在Scheme中,(define n1 n2)表示"在当前环境中设置新绑定,名为n1,并指向表达式n2"的值。如果n2恰好是变量,则其值就是该变量的值 。这就是为什么我们谈论Scheme的评估语义。

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

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