我将元循环评估器的计算机程序结构和解释 (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值:
<环境图>
;;; 评估输入:
你好字符串
;;; 评估值:
你好
这表明可以在环境中存储和检索新帧。
最初设置环境true
并false
显式添加时:
(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 版本中可以正常工作(并且如果true
不false
添加到中则不起作用setup-environment
,因此它看起来eval
不会解释true
为需要在 Clojure 版本的环境中查找的内容。
不幸的是,我没有确切地看到这种查找在 Scheme 版本中是如何发生的,以及为什么它在 Clojure 版本中没有发生。
我希望有人能引导我朝着正确的方向前进,为什么要true
在 Scheme 中进行评估,而不是在元循环评估器的 Clojure 实现中。