Reputation: 1479
As written in another post I am writing a Shen compiler in Clojure.
For that I need a macro/function that receives a symbol as parameter and if a Shen function is bound to it it returns the function and if the symbol is defined as Clojure macro it should return the macro, so ((function or) true false)
should give the same result as (or true false)
.
My macro currently looks like:
(defmacro kl/function [x]
(cl/let [fn (symbol (cl/str (name x) "__fnPoF__"))]
(if (function? fn) `(eval ~fn) `(quote ~x))))
The "__fnPoF__" postfix is there because of the double namespace in Shen. (A value and a function can be assigned to the same symbol.)
My problem now is that ((function or) true false)
evaluates to false because it evaluates as ('or true false)
but if I leave out the "quote" (x
instead of `(quote ~x)
I get the following Exception:
kl=> (function *)
CompilerException java.lang.RuntimeException: Can't take value of a macro: #'kl/*, compiling:(NO_SOURCE_PATH:8)
Does someone have an idea how to solve this problem?
Upvotes: 2
Views: 613
Reputation: 92147
You can't "return" a macro, because macros have no value. But you can make (function or) expand to the symbol or; then the usual Clojure macroexpansion/evaluation mechanisms will do just what you want. So, while I don't know how Shen works, it seems like a simple change would be:
(defmacro kl/function [x]
(cl/let [fn (symbol (cl/str (name x) "__fnPoF__"))]
(if (function? fn)
`(eval ~fn)
x)))
As an aside, that eval
strikes me as a disaster waiting to happen. I strongly doubt that eval
is necessary for your goals.
Upvotes: 3