3

我将元循环评估器的计算机程序结构和解释 (SICP)版本转换为 Clojure。主要区别(除了语法)是环境结构的处理。由于您不能在 Clojure 中使用set-car!set-cdr!,因此这些是通过一个持有地图的原子来实现的(从GitHub 上 Greg Sexton 的第 4 章注释的代码复制而来)。

两个评估器的代码可以在这里找到:

主程序eval进行案例分析,然后决定下一步如何处理exp环境中的表达式env

(defn eval [exp env]
  (cond (self-evaluating? exp) exp
        (variable? exp) (lookup-variable-value exp env)
        (quoted? exp) (text-of-quotation exp)
        (assignment? exp) (eval-assignment exp env)
        (definition? exp) (eval-definition exp env)
        (if? exp) (eval-if exp env)
        (lambda? exp) (make-procedure (lambda-parameters exp) 
                                      (lambda-body exp)
                                      env)
        (begin? exp) (eval-sequence (begin-actions exp) env)
        (cond? exp) (eval (cond->if exp) env)
        (application? exp) (apply (eval (operator exp) env)
                                  (list-of-values (operands exp) env))
        :else (throw (Throwable. (str "Unknown expression type \"" exp "\" -- EVAL")))))

与 Clojure 评估器交互时,您可以执行以下操作:

;;; 评估输入:
(defn hello-string hello)

;;; eval值:
<环境图>

;;; 评估输入:
你好字符串

;;; 评估值:
你好

这表明可以在环境中存储和检索新帧。

最初设置环境truefalse显式添加时:

(defn 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))

但是当输入 if 表达式时,代码会失败,因为它找不到“true”。(如果您只评估true,也会发生同样的情况,在 Scheme 版本中评估为#t)。

;;; 评估输入:(
如果为真 hello-string "hi")
CompilerException java.lang.Throwable: 未知表达式类型 "true" --
EVAL,编译:(/home/erooijak/clojure/scheme-interpreter/scheme-
evaluator.clj: 314:1)

(我希望这被评估为“你好”)

由于eval-if在 Scheme 版本中可以正常工作(并且如果truefalse添加到中则不起作用setup-environment,因此它看起来eval不会解释true为需要在 Clojure 版本的环境中查找的内容。

不幸的是,我没有确切地看到这种查找在 Scheme 版本中是如何发生的,以及为什么它在 Clojure 版本中没有发生。

我希望有人能引导我朝着正确的方向前进,为什么要true在 Scheme 中进行评估,而不是在元循环评估器的 Clojure 实现中。

4

1 回答 1

3

我假设您正在使用 Clojure 的内置阅读器,而不是根据字符串输入自己实现它。true并且false不要读取为符号,而是读取为布尔值,然后您的variable?函数可能不会为布尔值返回 true。

相关地,你写(define-variable! 'true true initial-env),好像你相信'true并且true是不同的价值观;它们是一样的,就像'66一样。

于 2016-04-09T02:28:34.123 回答