我正在尝试根据 Harold Abelson 和 Gerald Jay Sussman 的著名书籍“计算机程序的结构和解释”在 Scheme 中实现 Metacircular Evaluator。
http://mitpress.mit.edu/sicp/full-text/sicp/book/node79.html , http://mitpress.mit.edu/sicp/full-text/sicp/book/node80.html
作者建议这样设置环境:
(define (define-variable! var val env)
(let ((frame (first-frame env)))
(define (scan vars vals)
(cond ((null? vars)
(add-binding-to-frame! var val frame))
((eq? var (car vars))
(set-car! vals val))
(else (scan (cdr vars) (cdr vals)))))
(scan (frame-variables frame)
(frame-values frame))))
(define (setup-environment)
(let ((initial-env
(extend-environment (primitive-procedure-names)
(primitive-procedure-objects)
the-empty-environment)))
(define-variable! 'true true initial-env)
(define-variable! 'false false initial-env)
initial-env))
但是,我不明白为什么
(define myenv (setup-environment))
在 Scheme 中应该能像我们预期的那样工作,因为据我所知,Scheme 默认情况下按值将变量传递给函数,因此在两次应用“define-variable!”之后initial-env,initial-env不会每次都改变,setup-environment函数会返回extend-environment返回的值。
我哪里理解有误,请指教?
提前致谢!
最佳答案
您的问题可能很小更具体一些,但我相信我理解。
具体来说,您的问题似乎是这样的:
“我对
的行为感到惊讶(define myenv (setup-environment))
(define-variable! 'a 13 myenv)
(lookup myenv 'a)
具体来说,我预计它会失败,因为 Scheme 是按值调用的。”这是你的问题吗?
如果是这样,那么我想我可以回答。按值调用并不意味着值不能改变。它只是意味着函数调用涉及将值从调用者传递给被调用者。事实上,几乎所有的语言都是按值调用的。这个词被广泛误解。例如,Java 也是一种按值调用的语言。
那么,Scheme 没有任何东西可以阻止您更改或“改变”一个值。在此示例中,set-car!
调用改变了它所引用的列表。然后,任何可以“看到”此值的代码段都可以看到此更改。
我认为您的基本问题确实与“按值调用”的含义有关,我希望我已经阐明了它。
关于lisp - 元循环评估器,实现环境,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9741411/