在第7章的Peter Norvig's史诗大片Paradigms of Artifical Intelligence Programming中 - 他描述了一个函数interp
,它实际上是一个简单的eval
函数,用于解释一个简单的方案。 REPL。
(defun interp (x &optional env)
"Interpret (evaluate) the expression x in the environment env."
(cond
((symbolp x) (get-var x env))
((atom x) x)
((case (first x)
(QUOTE (second x))
(BEGIN (last1 (mapcar #'(lambda (y) (interp y env))
(rest x))))
(SET! (set-var! (second x) (interp (third x) env) env))
(IF (if (interp (second x) env)
(interp (third x) env)
(interp (fourth x) env)))
(LAMBDA (let ((parms (second x))
(code (maybe-add 'begin (rest2 x))))
#'(lambda (&rest args)
(interp code (extend-env parms args env)))))
(t ;; a procedure application
(apply (interp (first x) env)
(mapcar #'(lambda (v) (interp v env))
(rest x))))))))
有趣的是 - Christian Queinnec's Lisp In Small Pieces的开篇章节具有非常相似的功能,他称之为eval
。
;;; This is a naive evaluator for Scheme written in naive Scheme.
(define (evaluate e env)
(if (atom? e)
(cond ((symbol? e) (lookup e env))
((or (number? e) (string? e) (char? e)
(boolean? e) (vector? e) )
e )
(else (wrong "Cannot evaluate" e)) )
(case (car e)
((quote) (cadr e))
((if) (if (evaluate (cadr e) env)
(evaluate (caddr e) env)
(evaluate (cadddr e) env) ))
((begin) (eprogn (cdr e) env))
((set!) (update! (cadr e) env (evaluate (caddr e) env)))
((lambda) (make-function (cadr e) (cddr e) env))
(else (invoke (evaluate (car e) env)
(evlis (cdr e) env) )) ) ) )
我的问题是 - Clojure源在哪里是等效的eval
/ interp
函数?我假设它在某处的读者代码中。
答案 0 :(得分:6)
你的意思是,什么是Clojure的eval
程序?那是clojure.core/eval。文档中的link显示了评估的发生方式:
eval
如果您对实际源代码感兴趣,请查看Clojure的core.clj
文件。特别是,eval
的代码如下所示:
(defn eval
"Evaluates the form data structure (not text!) and returns the result."
[form] (. clojure.lang.Compiler (eval form)))
反过来,eval
类中的Compiler
方法(在上面的代码段中引用,并驻留在Compiler.java文件中)如下所示:
public static Object eval(Object form) throws Exception{
boolean createdLoader = false;
if(true)//!LOADER.isBound())
{
Var.pushThreadBindings(RT.map(LOADER, RT.makeClassLoader()));
createdLoader = true;
}
try
{
Integer line = (Integer) LINE.deref();
if(RT.meta(form) != null && RT.meta(form).containsKey(RT.LINE_KEY))
line = (Integer) RT.meta(form).valAt(RT.LINE_KEY);
Var.pushThreadBindings(RT.map(LINE, line));
try
{
form = macroexpand(form);
if(form instanceof IPersistentCollection && Util.equals(RT.first(form), DO))
{
ISeq s = RT.next(form);
for(; RT.next(s) != null; s = RT.next(s))
eval(RT.first(s));
return eval(RT.first(s));
}
else if(form instanceof IPersistentCollection
&& !(RT.first(form) instanceof Symbol
&& ((Symbol) RT.first(form)).name.startsWith("def")))
{
FnExpr fexpr = (FnExpr) analyze(C.EXPRESSION, RT.list(FN, PersistentVector.EMPTY, form), "eval");
IFn fn = (IFn) fexpr.eval();
return fn.invoke();
}
else
{
Expr expr = analyze(C.EVAL, form);
return expr.eval();
}
}
finally
{
Var.popThreadBindings();
}
}
catch(Throwable e)
{
if(!(e instanceof CompilerException))
throw new CompilerException((String) SOURCE.deref(), (Integer) LINE.deref(), e);
else
throw (CompilerException) e;
}
finally
{
if(createdLoader)
Var.popThreadBindings();
}
}
我想这并不是你所期望的那样,但考虑到Clojure在JVM之上运行这一事实,评估部分作为Java程序而不是作为Lisp程序发生是有意义的 - 就像是问题中引用的代码中的大小写。