Clojure - (读取字符串字符串调用函数

时间:2012-02-06 11:13:47

标签: clojure resolve

我在clojure文件中有以下内容:

(ns helloworld
  (:gen-class
    :main -main))

(defn hello-world-fn []
  (println "Hello World"))

(defn -main [& args]
  (eval (read-string "(hello-world-fn)")))

我正在用

运行它
lein run helloworld

我收到以下错误:

Exception in thread "main" java.lang.RuntimeException: Unable to resolve symbol:
 helloworld in this context, compiling:(helloworld.clj:12)

我有一种感觉,我需要对ns-resolveresolve做些什么,但我没有取得任何成功。我在主函数中尝试了以下内容:

(let [call-string  (read-string "(hello-world-fn)")
      func (resolve  (symbol (first call-string)))
      args (rest call-string)]
   (apply func args))

没有成功。

某人(a)能指出我正确的方向; (b)准确解释Clojure读者在发生这种情况时会发生什么?

2 个答案:

答案 0 :(得分:6)

尝试查看-main内的实际命名空间。

(defn -main [& args]
  (prn *ns*)
  (eval (read-string "(hello-world-fn)")))

在用异常轰炸之前输出#<Namespace user>。这暗示使用lein run的程序的执行始于user命名空间,显然不包含hello-world-fn符号的映射。您需要明确限定它。

(defn -main [& args]
  (eval (read-string "(helloworld/hello-world-fn)")))

答案 1 :(得分:3)

您可以使用macros以非常优雅的方式解决您的挑战。实际上,您可以编写一个模仿eval

的宏
(defmacro my-eval [s] `~(read-string s))
(my-eval "(hello-world-fn)")); "Hello World"

它比eval效果更好,因为s的符号解析位于调用my-eval的上下文中。感谢@Matthias Benkard的澄清。

您可以在http://clojure.org/reader

中了解宏及其语法