将对象从java传递到Clojure eval
问题描述:
我从Java调用Clojure,并在传入的字符串上调用eval
。Java代码将保存对象,并且客户端代码可以指定要在对象上运行的Clojure代码字符串。我知道如何从Java调用Clojure代码,但是如何传递变量?将对象从java传递到Clojure eval
这是我的。首先,一个简单的工作对象:
public class Helloer {
public String getGreeting() { return "Hello"; }
}
然后一些样板代码调用Clojure方法。
public static String call(Helloer helloer, String expression) throws Exception {
RT.loadResourceScript("EvalObject.clj");
final Var schrodEval = RT.var("eval-object", "eval-string");
final String result = (String) schrodEval.invoke(expression, helloer);
return result;
}
但是后来我被困在Clojure代码中。该对象正常传递,但是如何将该值传递给eval
?
这是我已经试过:
(ns eval-object)
(defn eval-string [string this]
(eval (read-string string)))
(defn eval-string2 [string value]
(def this)
(binding [this value]
(eval (read-string string))))
(defn eval-string3 [string value]
(def this)
(eval (list 'binding (vector 'this 5) (read-string string))))
这些给:
java.lang.Exception: Unable to resolve symbol: this in this context (NO_SOURCE_FILE:0)
于是我试图构建一个定义this
具有约束力的条款:
(defn eval-string4 [string value]
(def this)
(eval (list 'do (list 'defonce 'this nil)
(list 'binding (vector 'this value) (read-string string)))))
但现在我得到:
java.lang.RuntimeException: Can't embed object in code, maybe print-dup not defined: [email protected] (NO_SOURCE_FILE:0)
我错过了什么吗?是否有可能将对象从Java,Clojure传递到eval?
答
原来错误信息是正确的。我需要定义print-dup
。我实现了Helloer
类简单的ID查找,并定义为print-dup
:
(defmethod print-dup com.ziroby.Helloer [h stream]
(.write stream "#=(com.ziroby.Helloer/getById ")
(.write stream (str (.getId h)))
(.write stream ")"))
显然,Clojure中需要一些方法来打印的目的是能够把它变成一个eval语句。这个print-dup
创建一个Clojure语句来通过Helloer.getById
(它只是在一个散列表中查找对象)查找对象来“创建”对象。
正如@mikera所说,如果您接受来自调用者的任意代码或动态生成代码,则只需跳过这些环节即可。
答
这并不完全清楚你的意思是“传递对象到评估”。也许你可以澄清目标多一点?
然而,它可能是你正在寻找的东西是这样的:
(defn call-eval [helloer]
(eval `(.getGreeting ~helloer)))
(call-eval some-helloer)
=> "Hello"
几件事情需要注意:
- 当你做一个eval,您需要报价形式
- 要通过“对象”,您需要取消引用(
~
)在此表单中,以便该对象被使用dir而不仅仅是一个符号 - 你不需要eval因为
(.getGreeting helloer)
的工作原理也一样(因为它不需要编译表单,所以效率更高。通常情况下,只有在运行时动态生成新代码或者要读入并接受任意代码作为输入(例如REPL本身)时才需要eval。
我正在做eval的第二个例子。我想阅读并接受任意代码。我希望这个任意代码能够以'this'的形式访问'helloer'对象。 –