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

Clojure-(读取字符串调用函数),clojure,resolve,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 "ma

我在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 resolve
resolve
执行一些操作,但没有成功。我在主功能中尝试了以下操作:

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


有人能(a)为我指出正确的方向吗;以及(b)准确地解释发生这种情况时Clojure reader中发生了什么?

尝试查看
-main中的实际名称空间是什么

(defn -main [& args]
  (prn *ns*)
  (eval (read-string "(hello-world-fn)")))
它输出
#
,然后将异常炸出。这提示使用
lein run
运行的程序从
用户
名称空间开始执行,该名称空间显然不包含您的
hello world fn
符号的映射。您需要显式限定它

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

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

(defmacro my-eval [s] `~(read-string s))
(my-eval "(hello-world-fn)")); "Hello World"
eval
效果更好,因为
s
的符号解析发生在调用
my eval
的上下文中。感谢@Matthias Benkard的澄清


调用
(hello world fn)时,您可以在

中阅读宏及其语法
它直接工作。为什么它的行为不同于
eval
?@YehonathanSharvit,因为在这种情况下,符号
hello world fn
将在编译时解析,因此源文件顶部附近的命名空间声明是相关的。
(hello world fn)另一方面,
只是一个字符串。编译器不会通过查找字符串来限定它们的名称空间,因为这样做是错误的;因此,在运行时运行的
eval
,需要在执行时通过查看
*ns*
变量来解析名称引用。非常喜欢调试方法并解决它显然。我认为另一个更开箱即用,更优雅。请欣赏@MatthiasBenkard解释编译阶段。为什么这会在ns resolve没有解决名称空间问题时自动解决?hawkeye因为
resolve
在运行时工作,将解决当前名称空间中的符号,无论
*ns*
变量当时指向,而文件上下文中的宏扩展代码由文件编译器处理,它根据文件中的命名空间声明解析符号。谢谢-如果在关于的示例中,
*ns*
已经指向helloworld-为什么它不
解析函数?@hawkeye您需要严格区分运行时和编译时。在编译时,已知正在编译的名称空间,但编译后,代码完全解析并限定名称空间,因此独立于运行时当前名称空间。传递给
eval
的代码基于当调用在另一个命名空间中编译的函数时,
*ns*
变量在该时间点,即在运行时,而不是在编译时。您必须手动绑定
*ns*
。更加优雅和灵活。非常喜欢@MatthiasBenkard的解释。