Вызов макроса против среды определения макроса в Julia

Я пытаюсь понять смысл утверждения в документации по метапрограммированию Джулии на макросигиена. В документации утверждается, что

Макроэкспандер Джулии решает эти проблемы следующим образом. Во-первых, переменные в результате макроса классифицируются как локальные или глобальные. Переменная считается локальной, если она назначена (а не объявлена ​​глобальной), объявлена ​​локальной или используется в качестве имени аргумента функции. В противном случае он считается глобальным. Затем локальные переменные переименовываются в уникальные (с помощью функции 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 не нужно здесь использовать?

РЕДАКТИРОВАТЬ (УТОЧНЕНИЕ)

  1. Когда я утверждаю, что f является глобальным, а x является локальным, согласно документации, я делаю это потому, что вижу, что x используется в качестве аргумента функции. Я понимаю, что x не записывается и не объявляется локальным, и он определенно выглядит глобальным, но эти документы утверждают, что аргументы функции также должны быть глобальными!

  2. Я знаю обычную часть гигиены, когда генсимминг локальных переменных гарантирует, что переменные с тем же именем в контексте вызывающего макроса не будут случайно замазаны. Однако в документации утверждается, что для функций те, которые видны в контексте определения макроса, защищены от вызывающей стороны, используя их собственные. Это часть, которая для меня не имеет смысла, потому что мой эксперимент показывает обратное.


person Ray Toal    schedule 29.11.2015    source источник
comment
см. github.com/JuliaLang/julia/issues/4873   -  person Isaiah Norton    schedule 30.11.2015
comment
Вау, это все еще нерешенная проблема?   -  person Ray Toal    schedule 30.11.2015


Ответы (1)


Это ошибка. Это старая проблема Julia 0.5 и ранее, исправленная в Julia 0.6. См. https://github.com/JuliaLang/julia/issues/4873 для получения дополнительной информации. Информация.

person Fengyang Wang    schedule 11.04.2017
comment
Я наконец дошел до установки 0.6, и теперь все стало лучше. - person Ray Toal; 02.09.2017