我将元循环评估程序的Structure and Interpretation of Computer Programs (SICP)版本转换为Clojure。主要区别(除了语法)是环境结构的处理。由于您无法在Clojure中使用set-car!
和set-cdr!
,因此这些是通过持有地图的原子(从Greg Sexton's chapter 4 notes on GitHub的代码复制而来实现的,我相信它具有相同的问题而无法使用定义程序)。
这两个评估者的代码可以在这里找到:
不幸的是,定义一个过程无法正常工作。我期望发生的是:
;;; M-Eval输入:
(defn(add1 x)(+ x 1))
;;; M-Eval值:
<环境印刷>
;;; M-Eval输入:
(add1 10)
;;; M-Eval值:
11
注意:它基本上是输入的代码,除了定义名为defn。
这里定义add1
在环境结构中存储一个过程,当用(add1 10
调用它时)在环境中查找符号add1
,并且评估者创建的过程是适用于10,结果为11。
但我看到的是:
;;; M-Eval输入:
(defn(add1 x)(+ x 1))
;;; M-Eval值:
{add1(procedure(x)(((+ x 1)))(#object [clojure.lang.Atom 0x7c197838 {:status:ready,:val {add1(procedure(x)(((+ x 1))) (#object [clojure.lang.Atom 0x7c197838 {:status:ready,:val {add1(procedure(x)(((+ x 1)))(#object [clojure.lang.Atom 0x7c197838 {:status:ready, :val {add1(procedure(x)(((+ x 1)))(#object [clojure.lang.Atom 0x7c197838 {:status:ready,:val {add1(procedure(x)((+ x 1)) ))(...等等)
我得到一个很长的环境输出(看起来创建的过程有一个包含过程本身的环境),然后是一个StackOverflowError。
- 未处理的clojure.lang.Compiler $ CompilerException
编译错误:
方案-evaluator.clj:316:1
(...)
- 由java.lang.StackOverflowError引起的 (没有消息)
醇>
为清楚起见,我将eval
放在下面。但我认为the whole code需要运行才能正确看出错误。
(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")))))
我希望有人能帮助我解决这个问题,或许可以对这里出了什么问题有所了解。
答案 0 :(得分:1)
问题是lambda-body
程序。 lambda
列表包含3个元素;标签,参数和它的主体。但是,按lambda-body
检索正文会使用cddr
而不是caddr
,因此结果会被额外列表包裹。因此,如果您更改lambda-body
的定义,请执行以下操作:
(defn lambda-body [exp] (third exp))
然后你可以得到计算结果。
注意:如果您想避免堆栈溢出错误,那么您可以更改eval-definition
或define-variable!
以返回其他内容,例如给定exp
的名称。