考虑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 回答
你的第2点到第5点是正确的 . 在你的观点1中,
f
和make-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
表达式的值,将函数的参数绑定到此值,然后在结果环境中评估函数的主体来计算: