Reputation: 328
I have a problem when I'm using macros in clojure. Here is what I'm trying to do.
(defmacro working-example []
'(+ foo 1))
(defn working-function [foo]
(working-example))
(working-function 2) ; => 3
(defmacro broken-example [bar]
`(+ foo ~bar))
(defn broken-function [foo]
(broken-example 1)) ; => I get error here.
(broken-function 2) ; Should be 3.
I want the broken-example macro to only replace text just like working-example does. Why doesn't it work and how should do I get it to work?
Upvotes: 2
Views: 747
Reputation: 29021
I'm fairly new to Clojure, but I'll try to explain you what's happening here. Quoting and backquoting are different in how they treat symbols. For example, you can write similar code that result in subtle differences:
user=> '(+ foo 2)
(+ foo 2)
user=> `(+ foo 2)
(clojure.core/+ user/foo 2)
Note how just using backquote "binds" the symbols to the corresponding namespace (clojure.core
for +
and user
for foo
). In the contrary, quoting just treats the symbol as-is. If you want to correctly write your broken function, you can use the list
syntax:
(defmacro broken-example [bar]
(list '+ 'foo bar))
(defn broken-function [foo]
(broken-example 1))
(broken-function 2)
Now broken-function
outputs the expected result.
EDIT:
Now thanks to A. Webb comment below, you can also avoid the namespace binding by using this syntax:
(defmacro broken-example [bar]
`(+ ~'foo ~bar))
Upvotes: 5