Macros transform syntax to syntax. Normally you return syntax in the form of a quoted expression from a macro, but if you leave out the quotes, what you return is just treated as a constant. Inside the macro body, criteria is :x, i.e. a symbol named x (the syntax that constitutes the macro’s input); the macro body never sees the value bound to x. Once you understand that, it follows that e.g. "$(:x)" is just the string "x" (which you can test at the REPL as well), and that’s why you get this result.
What you want instead is to have the macro create code (in the form of a quoted expression) that references x. This is made a little bit more confusing in this case by the fact that $ is used both to interpolate into quoted expressions, as well as to interpolate into strings. To avoid this confusion, I’d propose doing the string interpolation in a separate function, called in the code generated by the macro. Furthermore, you’ll should escape the input using esc:
criteria_string(criteria) = """ "$criteria," """ # *string* interpolation
macro SW2(criteria)
return quote
println(criteria_string($(esc(criteria)))) # *expression* interpolation
end
end
If you’re wondering what happens when you don’t use esc, here’s an example:
module M
export @SW2
x = 1
criteria_string(criteria) = """ "$criteria," """
macro SW2(criteria)
return quote
println(criteria_string($criteria))
end
end
end
using Main.M
x = 2
@SW2(x)
Which prints "1,"! This is because without esc, x will be resolved in the macro definition environment (i.e. module M), while you want it to refer to the x that’s in the macro call environment (the one outside M).