在 Clojure 的元循环求值器中求值 "true"

Evaluating "true" in meta-circular evaluator in Clojure

我转换了 Structure and Interpretation of Computer Programs (SICP) version of the meta-circular evaluator to Clojure. The main difference (besides syntax) is the handling of the environment structure. Since you cannot use set-car! and set-cdr! in Clojure, these are implemented via an atom holding a map (copied from the code of Greg Sexton's chapter 4 notes on GitHub).

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

主程序 eval 进行案例分析,然后决定下一步在环境 env:

中使用表达式 exp 做什么
(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 求值器交互时,您可以执行以下操作:

;;; Eval input:
(defn hello-string hello)

;;; Eval value:
< environment map >

;;; Eval input:
hello-string

;;; Eval value:
hello

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

最初设置环境时,明确添加了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)。

;;; Eval input:
(if true hello-string "hi")
CompilerException java.lang.Throwable: Unknown expression type "true" --
EVAL, compiling:(/home/erooijak/clojure/scheme-interpreter/scheme-
evaluator.clj:314:1)

(I would expect this to be evaluated to "hello")

因为 eval-if 在 Scheme 版本中可以正常工作(如果 truefalse 没有添加到 setup-environment 就不能工作,它看起来像 eval 不会将 true 解释为需要在 Clojure 版本的环境中查找的内容。

不幸的是,我不明白这种查找在 Scheme 版本中是如何发生的,以及为什么在 Clojure 版本中没有发生。

我希望有人能引导我朝着正确的方向前进,了解为什么 true 在 Scheme 中有效,但在元循环评估器的 Clojure 实现中无效。

我假设您正在使用 Clojure 的内置 reader,而不是基于字符串输入自己实现它。 truefalse 不读作符号,而是读作布尔值,然后您的 variable? 函数可能不 return 布尔值。

相关地,你写(define-variable! 'true true initial-env),好像你认为'truetrue是不同的值;它们是相同的,就像 '66 是相同的。