I am very new to Clojure and completely new to macro system. I am writing a task management system in clojure where I send a piece of clojure code as EDN from one node to another.
To make things less messy, I created a macro called deftask where I associate a name with some code that I send as EDN to another node which evaluates and executes it.
(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.")))
on the subscriber, this edn is converted to code, and then executed.
However I need to use require and include tasks.test.task
other wise eval gets an exception while trying to understand tasks.test.task
.
Is there a better way to define the macro, so that I can pass full qualified name of a function without having such trouble ?
Here is my code at the subscriber side:
(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)))))
whenever I don't use use require to include tasks.test.task
there, catch block executes and the message I get is this:
Ex: tasks.test.task
Thats it!
ClassNotFoundException
. And yes, you have to add a(require 'tasks.test.task)
either to the code sent by your producer or before evaluation of the form in your consumer. In both cases you can probably create a list of namespaces-to-require programmatically by recursively walking the code (or using zippers) and finding all fully qualified symbols. – xsc