Макрос hygiene
важен: «макросы должны обеспечивать, чтобы переменные, которые они вводят в возвращаемые выражения, не конфликтовали случайно с существующими переменными в окружающем коде, в который они расширяются». В документах есть раздел. Проще всего показать простой случай:
macro foo(x)
return :($x)
end
Когда вы вводите обычное выражение в REPL, оно вычисляется немедленно. Чтобы подавить эту оценку, окружите выражение :( )
.
julia> 1 + 1
2
julia> :(1 + 1)
:(1 + 1)
# note this is the same result as you get using Meta.parse
julia> Meta.parse("1 + 1")
:(1 + 1)
. Таким образом, Meta.parse
преобразует соответствующую строку в выражение. И если вы eval
результат, выражение будет оценено. Обратите внимание, что печать простого выражения удаляет внешние :( )
julia> expr = Meta.parse("1 + 1")
:(1 + 1)
julia> print(expr)
1 + 1
julia> result = eval(expr)
2
Обычно макросы используются для манипулирования вещами перед обычной оценкой выражений;в основном это синтаксические преобразования. Макросы выполняются до того, как другой исходный код скомпилирован / оценен / выполнен.
Вместо того, чтобы искать макрос, который оценивает строку, как если бы она была набрана непосредственно в REPL (без кавычек), используйте эту функцию вместо этого.
evalstr(x::AbstractString) = eval(Meta.parse(x))
Хотя я не рекомендую этот следующий макрос, полезно знать технику. Макрос с именем <name>_str
используется следующим образом: <name>"<string contents>"
:
julia> macro eval_str(x)
:(eval(Meta.parse($x)))
end
julia> eval"1 + 1"
2
(ps не используйте имена базовых функций в качестве имен переменных, используйте str
, а не string
)
Пожалуйста, дайте мне знать, если есть что-то, к чему я не обращался.