Я пытаюсь понять смысл утверждения в документации по метапрограммированию Джулии на макросигиена. В документации утверждается, что
Макроэкспандер Джулии решает эти проблемы следующим образом. Во-первых, переменные в результате макроса классифицируются как локальные или глобальные. Переменная считается локальной, если она назначена (а не объявлена глобальной), объявлена локальной или используется в качестве имени аргумента функции. В противном случае он считается глобальным. Затем локальные переменные переименовываются в уникальные (с помощью функции gensym (), которая генерирует новые символы), а глобальные переменные разрешаются в среде определения макроса. Таким образом, решаются обе вышеуказанные проблемы; локальные переменные макроса не будут конфликтовать ни с какими пользовательскими переменными, а time и println будут ссылаться на определения стандартной библиотеки.
Я написал небольшую программу, чтобы увидеть, действительно ли глобальные переменные разрешены в среде определения макросов. Я написал следующее:
f(x) = x + 100
macro g() # According to Julia docs, ...
:(f(x) + 5) # ... f is global, x is local, right?
end # if so, f should refer to the f above?
(function main()
local x = 3
f(x) = x - 100 # f in the call environment subtracts 100
println(@g()) # So why does this do -92?
end)()
Если я должен правильно понимать документацию Джулии, часть макро-гигиены состоит в том, чтобы убедиться, что какие бы функции ни вызывались в возвращаемом выражении макроса, не были захвачены функциями с тем же именем внутри среды вызывающего. Но это именно то, что здесь происходит, функция f
, которая использовалась, была той, которая была определена локально.
Я бы подумал, что мне придется использовать esc
, чтобы использовать f
в области видимости в точке вызова. Но это не так, почему?
Кроме того, я заметил, что переменная x
внутри результата макроса считается локальной, поэтому для нее должно было быть сгенерировано новое имя переменной, чтобы не конфликтовать с x
в среде вызова макроса. Но и этого не произошло!
Как мне прочитать документацию, чтобы понять причину, по которой esc
не нужно здесь использовать?
РЕДАКТИРОВАТЬ (УТОЧНЕНИЕ)
Когда я утверждаю, что
f
является глобальным, аx
является локальным, согласно документации, я делаю это потому, что вижу, чтоx
используется в качестве аргумента функции. Я понимаю, чтоx
не записывается и не объявляется локальным, и он определенно выглядит глобальным, но эти документы утверждают, что аргументы функции также должны быть глобальными!Я знаю обычную часть гигиены, когда генсимминг локальных переменных гарантирует, что переменные с тем же именем в контексте вызывающего макроса не будут случайно замазаны. Однако в документации утверждается, что для функций те, которые видны в контексте определения макроса, защищены от вызывающей стороны, используя их собственные. Это часть, которая для меня не имеет смысла, потому что мой эксперимент показывает обратное.