Julia 宏中的无效赋值错误
Invalid assignment error inside Julia macro
我一直在关注 this 笔记本(最初是用 Julia 0.x 编写的,我正在使用 Julia 1.7.1)。其中一个单元格定义了以下宏。
macro twice(ex)
quote
$ex
$ex
end
end
在紧接着的下一个单元格中,将调用此宏。
x = 0
@twice println(x += 1)
在 REPL 中复制它(为简洁起见)会导致以下错误。
ERROR: syntax: invalid assignment location "Main.x" around REPL[1]:3
Stacktrace:
[1] top-level scope
@ REPL[4]:1
所以,我知道 x += 1
以某种方式导致了这个问题,但是在阅读了文档 (metaprogramming) 之后,我无法弄清楚 为什么这是一个分配无效 或如何解决此问题。
@macroexpand @twice println(x += 1)
成功returns以下
quote
#= REPL[1]:3 =#
Main.println(Main.x += 1)
#= REPL[1]:4 =#
Main.println(Main.x += 1)
end
所以,我尝试在没有 Main.
的顶层 eval
进行此操作,并且评估成功。
x = 0
eval(quote
println(x += 1)
println(x += 1)
end)
输出:
1
2
但是,如果我明确添加模块名称,它会引发不同的错误。
eval(quote
Main.println(Main.x += 1)
Main.println(Main.x += 1)
end)
ERROR: cannot assign variables in other modules
Stacktrace:
[1] setproperty!(x::Module, f::Symbol, v::Int64)
@ Base ./Base.jl:36
[2] top-level scope
@ REPL[14]:3
[3] eval
@ ./boot.jl:373 [inlined]
[4] eval(x::Expr)
@ Base.MainInclude ./client.jl:453
[5] top-level scope
@ REPL[14]:1
我尝试了一些其他的东西,但这些是我认为可能有所作为的唯一东西。
- 为什么第一个宏代码块中的赋值无效?是否出于与指定模块
Main
在顶层中 eval
ing 失败相同的原因?
- 如何规避此无效分配,或者如何将其移植到 Julia 1.7?
使用esc
(这“防止宏卫生传递将嵌入变量转换为gensym变量”):
julia> macro twice(ex)
esc(quote
$ex
$ex
end)
end;
julia> x=1
1
julia> @twice println(x += 1)
2
3
我一直在关注 this 笔记本(最初是用 Julia 0.x 编写的,我正在使用 Julia 1.7.1)。其中一个单元格定义了以下宏。
macro twice(ex)
quote
$ex
$ex
end
end
在紧接着的下一个单元格中,将调用此宏。
x = 0
@twice println(x += 1)
在 REPL 中复制它(为简洁起见)会导致以下错误。
ERROR: syntax: invalid assignment location "Main.x" around REPL[1]:3
Stacktrace:
[1] top-level scope
@ REPL[4]:1
所以,我知道 x += 1
以某种方式导致了这个问题,但是在阅读了文档 (metaprogramming) 之后,我无法弄清楚 为什么这是一个分配无效 或如何解决此问题。
@macroexpand @twice println(x += 1)
成功returns以下
quote
#= REPL[1]:3 =#
Main.println(Main.x += 1)
#= REPL[1]:4 =#
Main.println(Main.x += 1)
end
所以,我尝试在没有 Main.
的顶层 eval
进行此操作,并且评估成功。
x = 0
eval(quote
println(x += 1)
println(x += 1)
end)
输出:
1
2
但是,如果我明确添加模块名称,它会引发不同的错误。
eval(quote
Main.println(Main.x += 1)
Main.println(Main.x += 1)
end)
ERROR: cannot assign variables in other modules
Stacktrace:
[1] setproperty!(x::Module, f::Symbol, v::Int64)
@ Base ./Base.jl:36
[2] top-level scope
@ REPL[14]:3
[3] eval
@ ./boot.jl:373 [inlined]
[4] eval(x::Expr)
@ Base.MainInclude ./client.jl:453
[5] top-level scope
@ REPL[14]:1
我尝试了一些其他的东西,但这些是我认为可能有所作为的唯一东西。
- 为什么第一个宏代码块中的赋值无效?是否出于与指定模块
Main
在顶层中eval
ing 失败相同的原因? - 如何规避此无效分配,或者如何将其移植到 Julia 1.7?
使用esc
(这“防止宏卫生传递将嵌入变量转换为gensym变量”):
julia> macro twice(ex)
esc(quote
$ex
$ex
end)
end;
julia> x=1
1
julia> @twice println(x += 1)
2
3