Given the macro below -
(defmacro defhello [fn-name body] `(defn ~fn-name [~'name] ~body))
and a function defined when called as -
(defhello greeting (str "Hello" name))
and called as
(greeting "Joe")
, will return
Hello Joe
I do not understand the usage of ~' in front of the name parameter? What does it do? Don't quote (') and unquote (~) cancel each other? What happens when they are used together? Why not just write name without them?
In short, the ~
evaluates the expression in the syntax-quoted form just like it does for ~fn-name
. In this case, the expression to evaluate is 'name
, in which the result is the unqualified symbol name
.
However, lets break this down one piece at a time.
If you only had the unqualified symbol name
, it would be evaluated to clojure.core/name
at runtime1. This would result in an incorrect defn
form and cause a compiler exception.
(defn greeting [clojure.core/name] (str "Hello" name))
If you only had the quoted unqualified symbol 'name
, it would still be evaluated at runtime. The difference is that it would expand to (quote clojure.core/name)
. Again, this would result in an incorrect defn
form and cause a compiler exception.
(defn greeting [(quote clojure.core/name)] (str "Hello" name))
Finally, by using ~'name
, you will have the quoted form evaluated at compile-time, resulting in the unqualified symbol name
, leaving you with a proper defn
form.
(defn greeting [name] (str "Hello" name))
1 - This is true for this example because it assumes another name
function does not exist.
As I understand it, you quote the function definition, so it will not be evaluated when the macro is defined. You use the unquote operator ~
, to evaluate name in the definition. If name were a kind of list ~@
(unquote splice) would evaluate the elements of a list without the surrounding brackets.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With