我正在尝试写一个简单的swap!
Julia 中的宏,了解宏系统。到目前为止,这是我的代码:
macro swap!(x, y)
quote
local tmp = $(esc(y))
$x = $(esc(y))
$y = tmp
end
end
a = 1
b = 2
@swap!(a, b)
# prints: a: 1, b: 2
println("a: $a, b: $b")
这运行时没有错误,但实际上并没有更改值。 Julia 似乎没有一个只扩展宏而不执行它们的函数(据我所知),所以这很难调试。
REPL 中的等效引用似乎按预期工作:
julia> a = 1
1
julia> a_sym = :a
:a
julia> a_sym
:a
julia> b = 2
2
julia> b_sym = :b
:b
julia> eval(quote
tmp = $a_sym
$a_sym = $b
$b_sym = tmp
end)
1
julia> a
2
julia> b
1
我究竟做错了什么?
我想你可能想要像下面这样的东西,但被搞乱了hygiene http://julia.readthedocs.org/en/latest/manual/metaprogramming/#hygiene。诀窍是正确逃脱。
macro swap(x,y)
quote
local tmp = $(esc(x))
$(esc(x)) = $(esc(y))
$(esc(y)) = tmp
end
end
这是扩展后的样子
julia> macroexpand(quote @swap(x,y) end)
quote # none, line 1:
begin # none, line 3:
local #189#tmp = x # line 4:
x = y # line 5:
y = #189#tmp
end
end
效果
julia> x
1
julia> y
2
julia> @swap(x,y)
julia> x
2
julia> y
1
相比之下,您的宏在一个赋值中正确地转义了 y,但在其他 2 个语句中却没有转义,因此设置了引入变量的值,而不是预期的 x 和 y。
julia> macroexpand(quote @swap!(x,y) end)
quote # none, line 1:
begin # none, line 3:
local #208#tmp = y # line 4:
#209#x = y # line 5:
#210#y = #208#tmp
end
end
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)