Чтобы добиться желаемого, вам нужно использовать esc
:
macro t(a, b, c)
quote
local a1 = $(esc(a))
local b1 = $(esc(b))
local c1 = $(esc(c))
println(:c, " = ", c1)
(a1, b1, c1)
end
end
Обратите внимание, что я определяю переменные a1
, b1
и c1
один раз, а затем снова их использую. Причина в том, что если вы написали что-то вроде:
macro t(a, b, c)
quote
println(:c, " = ", $(esc(c)))
($(esc(a)), $(esc(b)), $(esc(c)))
end
end
, что естественно (или, возможно, нет :)), вы получите проблемы, поскольку c
будет оцениваться дважды, как, например. в этом примере:
julia> macro t(a, b, c)
quote
println(:c, " = ", $(esc(c)))
($(esc(a)), $(esc(b)), $(esc(c)))
end
end
@t (macro with 1 method)
julia> function test()
@t 1 2 rand()
end
test (generic function with 1 method)
julia> test()
c = 0.03771143425073453
(1, 2, 0.1819496773810383)
Обратите внимание, что печатается другое значение и возвращается другое значение. Эта проблема присутствовала в вашем исходном макросе (даже если он использовал глобальные переменные, как заметил @Bill):
julia> macro t(a, b, c)
quote
println(:c, " = " , $c)
($a, $b, $c)
end
end
@t (macro with 1 method)
julia> @t 1 2 rand()
c = 0.7021554643798531
(1, 2, 0.6363717837673994)
В общем, я думаю, что макросы @code_lowered
и @macroexpand
будут вам полезны, когда вы код отладки с использованием метапрограммирования.