Is there a comfortable way to implement a mechanism that takes a list, searches for the keyword clj
and evaluate what is inside the clj
?
Here an example:
'(a (clj (+ 1 1)) b) => '(a 2 b)
My first try was a function eval-clj
, that goes through the list and calls eval
for the clj
expressions. But that is not practicable, because the eval would not be in the right context. The example below would not work, because the variable x is not visible. There seems to be no way to achieve this with functions.
(let [x]
(eval-clj '(a (clj x) b)))
So I try it with a macro.
(defmacro eval-clj [expr]
(list 'list (list 'quote (nth expr 0)) (second (nth expr 1)) (list 'quote (nth expr 2))))
(macroexpand-1 '(eval-clj (a (clj (+ 1 1)) b)))
(eval-clj (a (clj (+ 1 1)) b))
It is just a small example. But it looks to me very complicated. I have to move the quotes from outside to inside. I would have to do it recursively.
And the macro solution does not handle dynamic things. This would not work:
(eval-clj (clj (map identity '(a b c))))
I understand why this does not work and why it is so complicated. But is there any idea to do such things? My use case is a domain specific language for something which is outside of Clojure, where the code is created at run time.
It would be very nice if my DSL could look like code. For example it would be nice to use expressions like '(schedule-task some-task-id)
without the need to actually defining these symbols.
I have the impression that what I want is theoretically impossible. Are such things may be possible in other languages like Racket? People say often that Racket is good for language designers.
What I find strange that the following things work
(clojure.edn/read-string "(set-name \"Sarah\")")
(let [name "Sarah"] (str (hiccup.page/html5 [:p "name: " name])))
while for our own data structures this is not possible:
(let [name "Sarah"] '(set-name name))
The workaround below does not look much like a DSL.
(let [name "Sarah"] (list 'set-name name))
I don’t know, if everybody can follow me. If nobody has an answer, that is ok. I just leave here what I found out in case someone finds it interesting.