sole
1
一个普通的模块定义,其中包含宏 @extend
module mymacro
export @extend
macro extend(name,vecs)
@eval Base.length(m::$name)=length(m.$vecs)
end
end
然后定义一个结构体
mutable struct shell
blocks::Vector
function shell()
c1 = "a"
c2 = "b"
c3 = "c"
new([c1,c2,c3])
end
end
对结构体执行宏的时候结果得到
julia> mymacro.@extend(shell,blocks)
ERROR: LoadError: UndefVarError: shell not defined
Stacktrace:
[1] top-level scope
@ none:1
[2] eval(m::Module, e::Any)
@ Core .\boot.jl:360
[3] var"@extend"(__source__::LineNumberNode, __module__::Module, name::Any, vecs::Any)
@ Main.mymacro .\REPL[7]:6
in expression starting at REPL[9]:1
但是当我在模块外部定义同样宏的时候
macro extend2(name,vecs)
@eval Base.length(m::$name)=length(m.$vecs)
end
然后执行
julia> @extend2(shell,blocks)
julia> s = shell();length(s)
3
却可以得到想要的效果。使用模块里的宏扩展模块外的结构体的方法就不行? 
求解决方案!谢谢! 
宏展开有上下文,直接 @eval
会在宏定义处展开并执行表达式。
可以直接返回表达式,并推迟展开类型名,让它在调用处求值。
module mymacro
export @extend
macro extend(name, vecs)
quote
Base.length(m::$(esc(name)))=length(m.$vecs)
end
end
end
调用输出
julia> module mymacro
export @extend
macro extend(name, vecs)
quote
Base.length(m::$(esc(name)))=length(m.$vecs)
end
end
macro old_extend(name,vecs)
quote
Base.length(m::$name)=length(m.$vecs)
end
end
end
Main.mymacro
julia> Main.mymacro.@extend shell blocks
julia> length(shell())
3
julia> macroexpand(Main, :(Main.mymacro.@extend shell blocks))
quote
#= REPL[2]:5 =#
(Main.mymacro.Base).length(var"#4#m"::shell) = begin
#= REPL[2]:5 =#
Main.mymacro.length((var"#4#m").blocks)
end
end
julia> macroexpand(Main, :(Main.mymacro.@old_extend shell blocks))
quote
#= REPL[2]:10 =#
(Main.mymacro.Base).length(var"#3#m"::Main.mymacro.shell) = begin
#= REPL[2]:10 =#
Main.mymacro.length((var"#3#m").blocks)
end
end
文档里有类似的例子:
注意它是在调用处直接 @eval
的,所以指定了类型名。
https://docs.juliacn.com/latest/manual/metaprogramming/#代码生成
1 个赞