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 个赞