【发布时间】:2013-12-01 12:12:26
【问题描述】:
我对 Clojure 非常陌生,对宏系统完全陌生。 我正在用 clojure 编写一个任务管理系统,我将一段 clojure 代码作为 EDN 从一个节点发送到另一个节点。
为了减少混乱,我创建了一个名为 deftask 的宏,在其中我将名称与一些代码关联起来,这些代码作为 EDN 发送到另一个节点,该节点评估并执行它。
(defmacro deftask
"Associates identifier with edn form of the code"
[id task]
`(def ~id (pr-str '~task)))
(deftask test-task
(tasks.test.task/execute "World!"
10
(ƒ [arg]
(println "Hello " arg))
(str "Successfully printed message " 10 " times.")))
在订阅者上,这个edn被转换成代码,然后被执行。
但是我需要使用 require 并包含 tasks.test.task 其他明智的 eval 在尝试理解 tasks.test.task 时会出现异常。
有没有更好的方法来定义宏,这样我就可以传递函数的完整限定名而不会遇到这样的麻烦?
这是我在订阅者端的代码:
(defn execute-edn-expression
"Evaluates and runs an expression written in Clojure EDN format"
[edn]
(try
(eval edn)
(catch Exception ex
(println "Ex: " (.getMessage ex)))))
每当我不使用 require 在其中包含 tasks.test.task 时,catch 块就会执行并且我得到的消息是这样的:
例如:tasks.test.task
就是这样!
【问题讨论】:
-
异常说什么?
-
检查我的更新。该异常只显示一条带有命名空间名称的消息。
-
为什么不在代码块中定义所需的命名空间需要呢?
-
对于任何想知道的人:
ClassNotFoundException是个例外。是的,您必须将(require 'tasks.test.task)添加到您的生产者发送的代码中,或者在评估您的消费者中的表单之前。在这两种情况下,您都可以通过递归遍历代码(或使用 zippers)并找到所有完全限定的符号,以编程方式创建一个需要命名空间的列表。 -
@GuillermoWinkler:我的问题是如果订阅者可以响应 100 个不同的任务调用,我将不得不在任何地方都包含命名空间。