Reputation: 12184
(defmacro switch [choices choice] '(do (choices choice)))
(macroexpand-1 '(switch {1 (print 1) 2 (print 2)} (+ 1 1)))
gives: (do (choices choice))
Just to learn macros, I wanted to emulate switch case where I will give a dictionary having case as keys and code to execute as values.
I wanted (+ 1 1) to get evaluated as 2 and then be used as key to get codde to execute with do.
However the expanded macro gives us code which doesn't resolve choices and choice both.
I tried unquoting choice and choices, doesn't work. What am I missing here ?
Upvotes: 1
Views: 76
Reputation: 84341
Unquoting does work, but you need to switch from the regular quote to syntax-quote (backtick) for your quoting:
(defmacro switch [choices choice]
`(do (~choices ~choice)))
Note that the do
here is unnecessary.
Note that with this version of switch
, both print
calls in your example will be evaluated, because they will simply appear as value expressions in a map literal in switch's output. To print conditionally, you'll have to use some conditional construct (if
, case
or something which expands to one of them). I'll also point out that the choices
argument must be a literal map, or else the macro won't be able to get at the keys and values (and in any case the values would have been evaluated by the outer context).
Here's a version written with the above in mind:
(defmacro switch [choices choice]
`(case ~choice ~@(apply concat choices)))
Example from the REPL:
user=> (switch {1 (print 1) 2 (print 2)} (+ 1 1))
2nil
(2
is printed by the print
call, nil
is the return value.)
Upvotes: 3