2012-03-16 61 views
3

我试图根据Harold Abelson和Gerald Jay Sussman着名的书籍“结构和计算机程序的解释”在计划中实现Metacircular Evaluator。Metacircular evaluation,implementation the environment

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默认将变量传递给函数,因此在两次将“define-variable!”应用于initial之后-env,initial-env不会每次都被更改,并且setup-environment函数将在extend-environment返回值时返回值。

我的理解错误在哪里,请问您能提供意见吗?

预先感谢您!

回答

5

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

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

“我通过

(define myenv (setup-environment)) 
(define-variable! 'a 13 myenv) 
(lookup myenv 'a) 

具体的行为感到惊讶,我希望它失败,因为计划是调用 - 值“。这是你的问题吗?

如果是这样,那么我想我可以回答它。拨打电话不是表示值不能更改。这只是意味着函数调用涉及将来自调用者的值传递给被调用者。事实上,几乎所有的语言都是按价值划分的;这个词被广泛误解。例如,Java也是一种按价值调用的语言。

没有什么关于Scheme的,那么,这可以防止你改变或“变异”一个值。在这个例子中,set-car!调用突变了它所指的列表。这个改变对于任何能够“看见”这个值的代码都是可见的。

我认为你的根本问题确实与“按价值划拨”的含义有关,我希望我已经阐明了一些看法。

+0

是的,很多人认为语言不是“按价值传递”,当他们真的是时,他们只是“按价值传递参考”。 – 2012-03-16 22:36:38

+0

非常感谢!你说得对,我的问题不是很准确,请原谅,请原谅。下一次会更清楚。 – 2012-03-17 11:07:19

2

要理解它是如何工作的,首先你要明白,变量initial-env将指向环境第一帧,而这个参考的是从未修改。环境本身是一个框架列表,每个框架是一对列表,第一个框架的car是变量列表的头部,第一个框架的cdr是值列表的头部。

一旦明确,您需要了解程序scanadd-binding-to-frame!的工作方式。 Scan将在当前帧的变量列表中查找与var同名的变量;如果找到它将替换值列表中的对应值。如果未找到该变量,add-binding-to-frame!将在相应列表的开头添加一个新变量和一个新值,更新框架以指向这个新的标题。请注意,initial-environment仍然指向第一帧,第一帧仍指向其变量和值列表的首部(但带有新的绑定)。

所以你现在看到,即使initial-env从未被改变过,它包含的列表也被修改了,因此增加了新的变量和它们各自的值。我相信理解整个过程的最好方法是抓住一支笔和一张纸,逐步绘制修改所涉及的cons单元格的结果。

+0

非常感谢! – 2012-03-17 04:02:48

+0

@Alfucio如果这个答案在任何方面对你有帮助,upvote会很好:) – 2012-03-17 13:04:30

+0

是的,我非常抱歉有两件事:首先,我不能将你的答案标记为已接受(tttt ,这对我来说很奇怪,我不能在这里,因为我相信经常有很多被接受的答案,例如,对于我目前的问题),尽管我认为你的答案和第一个答案一样有帮助(和我决定只标记第一个,因为它是第一个:));其次,我现在无法提出你的答案,因为我的声望点只有13。我一定会尽快上传你的帖子,我将会收到15页。再一次,非常感谢你,这真的很有帮助! – 2012-03-17 16:17:44