在 Julia 中转义宏生成宏中的表达式
Escaping expression in macro-generated-macro in Julia
我想在 Julia 中编写一个生成多个宏的宏
@register_attribute foo
应该生成宏
@set_foo
@get_foo
又应定义为
@set_foo x 5 == set_attr!(x, :foo, 5)
我已经成功地完成了第一部分,但是 @macroexpand
显示内部变量 x
没有正确转义,导致 UndefVarErrors
如果我调用带有局部变量的方法。
@macroexpand @set_foo x 5 =
:(Main.set_attr!(Main.x, (Symbol)("foo"), 5))
而我想要的是
@macroexpand @set_foo x 5 =
:(set_attr!(x, (Symbol)("foo"), 5))
我的密码是
macro register_attribute(name)
setn = Symbol("set_", string(name))
getn = Symbol("get_", string(name))
arg = gensym()
arg2 = gensym()
nsym = string(name)
return Expr(:block,
esc(:(
macro $(setn)($arg, $arg2)
:(set_attr!($$arg, $$Symbol($$nsym), $$arg2))
end)
),
esc(:(
macro $(getn)($arg, $arg2)
:(get_attr!($$arg, $$Symbol($$nsym), $$arg2))
end)
))
e2
end
以下是我处理整个问题的方法:
# for purely generative tasks like this, where the generated code is
# (presumably?) destined to be evalled at top level, I prefer using @eval
for attr in [:foo, :bar]
get_attr_name = Symbol("get_", attr)
set_attr_name = Symbol("set_", attr)
quoted_attr = QuoteNode(attr)
@eval begin
$get_attr_name(x) = getproperty( x, $quoted_attr)
$set_attr_name(x, val) = setproperty!(x, $quoted_attr, val)
end
end
# should generate code like:
# get_foo(x) = getproperty(x, :foo)
julia> nt = (foo=1, bar=2);
julia> get_foo(nt)
1
julia> get_bar(nt)
2
# Let's test in local scope too
julia> let nt2 = (foo=42,)
get_foo(nt2)
end
42
我想在 Julia 中编写一个生成多个宏的宏
@register_attribute foo
应该生成宏
@set_foo
@get_foo
又应定义为
@set_foo x 5 == set_attr!(x, :foo, 5)
我已经成功地完成了第一部分,但是 @macroexpand
显示内部变量 x
没有正确转义,导致 UndefVarErrors
如果我调用带有局部变量的方法。
@macroexpand @set_foo x 5 =
:(Main.set_attr!(Main.x, (Symbol)("foo"), 5))
而我想要的是
@macroexpand @set_foo x 5 =
:(set_attr!(x, (Symbol)("foo"), 5))
我的密码是
macro register_attribute(name)
setn = Symbol("set_", string(name))
getn = Symbol("get_", string(name))
arg = gensym()
arg2 = gensym()
nsym = string(name)
return Expr(:block,
esc(:(
macro $(setn)($arg, $arg2)
:(set_attr!($$arg, $$Symbol($$nsym), $$arg2))
end)
),
esc(:(
macro $(getn)($arg, $arg2)
:(get_attr!($$arg, $$Symbol($$nsym), $$arg2))
end)
))
e2
end
以下是我处理整个问题的方法:
# for purely generative tasks like this, where the generated code is
# (presumably?) destined to be evalled at top level, I prefer using @eval
for attr in [:foo, :bar]
get_attr_name = Symbol("get_", attr)
set_attr_name = Symbol("set_", attr)
quoted_attr = QuoteNode(attr)
@eval begin
$get_attr_name(x) = getproperty( x, $quoted_attr)
$set_attr_name(x, val) = setproperty!(x, $quoted_attr, val)
end
end
# should generate code like:
# get_foo(x) = getproperty(x, :foo)
julia> nt = (foo=1, bar=2);
julia> get_foo(nt)
1
julia> get_bar(nt)
2
# Let's test in local scope too
julia> let nt2 = (foo=42,)
get_foo(nt2)
end
42