Clojure - (read-string String calling function

元气小坏坏 提交于 2019-12-10 10:16:11

问题


I've got the following in a clojure file:

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

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

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

and I'm running it with

lein run helloworld

and I'm getting the following error:

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

I have a feeling I need to do something with ns-resolve or resolve but I haven't had any success. I've tried the following in the main function:

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

Without success.

Can someone (a) point me in the right direction; and (b) explain precisely what is going on in the Clojure reader when this occurs?


回答1:


You can solve your challenge, in a very elegant way, using macros. In fact, you can write a macro that mimics eval.

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

It works better that eval because the symbol resolution of s occurs in the context that calls my-eval. Thanks to @Matthias Benkard for the clarifications.

You can read about macros and their syntax in http://clojure.org/reader




回答2:


Try to see what the actual namespace is inside your -main.

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

It outputs #<Namespace user> before bombing out with the exception. This hints that execution of programs with lein run starts out in the user namespace, which obviously does not contain the mapping for your hello-world-fn symbol. You'll need to explicitly qualify it.

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


来源:https://stackoverflow.com/questions/9159268/clojure-read-string-string-calling-function

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!