Я нашел пример макроса unless
в Джулии здесь, написанный как следует:
macro unless(test, branch)
quote
if !$test
$branch
end
end
end
Однако, когда я пытаюсь использовать его, он терпит неудачу (видимо, есть проблема с гигиеной, но я не могу точно понять). Вот тест, который я использовал:
x, y = 0, 1
@unless (x == 5) begin # should execute
y = 3
end
@unless (x == 0) begin # should not execute
y = 5
end
@assert y == 3 # FAILS! SAYS y is 0
Теперь я могу заставить это работать, экранируя только ветку, а не тест:
macro unless(test, branch)
quote
if !$test
$(esc(branch))
end
end
end
Мой вопрос: почему достаточно только избежать ветки, но не теста? Теперь я попробовал макрорасширение. В первом случае без esc
я получаю это:
julia> macroexpand(:(@unless (x == 5) begin y = 3 end))
quote # none, line 3:
if !(x == 5) # none, line 4:
begin # none, line 1:
#2#y = 3
end
end
end
Теперь, несмотря на то, что ни один параметр макроса не был экранирован, ТОЛЬКО y
был сгенерирован! Кто-нибудь может объяснить, почему это произошло? (Я знаю, что вторая версия работает, потому что, когда я сбегаю из ветки, y не получает gensymed и макрос расширяется до y = 3
, как и ожидалось. Но я совершенно не понимаю, почему x
не был gensymed, хотя там было бесполезно esc
.)