Metacircular评估员,实施环境

时间:2012-03-16 16:58:14

标签: lisp scheme interpreter sicp metacircular

我正在尝试根据着名的书籍“#34;计算机程序的结构和解释”来实施计划中的元认知评估员。由Harold Abelson和Gerald Jay Sussman撰写。

http://mitpress.mit.edu/sicp/full-text/sicp/book/node79.htmlhttp://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返回时返回值。

我的理解错误在哪里,你能告诉我吗?

提前谢谢!

2 个答案:

答案 0 :(得分:5)

你的问题可能是一个更具体的 teensy ,但我相信我理解它。

具体来说,您的问题似乎是:

“我对

的行为感到惊讶
(define myenv (setup-environment))
(define-variable! 'a 13 myenv)
(lookup myenv 'a)

具体来说,我希望它会失败,因为Scheme是按值调用的。“这是你的问题吗?

如果是这样,那么我想我可以回答。按值调用表示值无法更改。它只是意味着函数调用涉及将值从调用者传递给被调用者。实际上,几乎所有语言都是按值调用的;这个词被广泛误解了。例如,Java也是一种按值调用的语言。

然后,没有什么可以阻止你改变或“改变”一个值。在此示例中,set-car!调用会改变它所引用的列表。然后,任何可以“看到”此值的代码都可以看到此更改。

我认为你的根本问题实际上与“价值呼唤”的含义有关,我希望我已经对它有所了解。

答案 1 :(得分:2)

要了解其工作原理,首先您必须了解变量initial-env将指向环境的第一帧,此引用 never < / em>已修改。环境本身是一个帧列表,每个帧是一对列表,第一帧的car是变量列表的头部,第一帧的cdr是价值清单的负责人。

一旦明确,您需要了解程序scanadd-binding-to-frame!的工作原理。对于与Scan同名的变量,var将在变量列表中查看当前帧内部;如果发现它将替换值列表中的相应值。如果找不到变量,add-binding-to-frame!将在相应列表的头部添加一个新变量和一个新值,更新帧以指向这个新头。请注意initial-environment仍然指向第一帧,第一帧仍然指向其变量和值列表的头部(但是使用新的绑定)。

所以你现在看到,即使initial-env从未改变,它包含的列表也会被修改,因此添加了具有各自值的新变量。我认为理解整个过程的最好方法是抓笔和纸,逐步绘制修改所涉及的利弊细胞的结果。