Julia-在运行时创建的函数中获取运行时参数

Julia-在运行时创建的函数中获取运行时参数,julia,metaprogramming,Julia,Metaprogramming,我正在尝试创建一个宏来替换函数体,以便: @foo function bar(a,b,c) *my code here* end 我已经做了很多,但是我这里的代码需要知道bar(…)的参数 通过使用Base.@locals。但是问题是,@foo需要插入它,我认为它使用了错误的“局部范围”,或者是在有参数之前进行了计算 foo大致如下:(expr.args[2]是函数体) 但是通过此调用后来创建的函数,只打印出一个空dict,而手动创建的函数在使用相同代码时会打印出参数: function

我正在尝试创建一个宏来替换函数体,以便:

@foo function bar(a,b,c)
   *my code here*
end
我已经做了很多,但是我这里的代码需要知道
bar(…)
的参数 通过使用
Base.@locals
。但是问题是,
@foo
需要插入它,我认为它使用了错误的“局部范围”,或者是在有参数之前进行了计算

foo大致如下:(
expr.args[2]
是函数体)

但是通过此调用后来创建的函数,只打印出一个空dict,而手动创建的函数在使用相同代码时会打印出参数:

function test(a,b,c)
    println(Base.@locals)
end
test(1,2,3) # returns: Dict{Symbol,Any}(:a => 1,:b => 2,:c => 3)

所以我的问题是,我必须如何解决这个问题,以便
Base.@locals
(或类似的方法)为我提供参数?

而不是依赖
Base.@locals
,我将直接从定义中获取函数参数,并执行如下操作:

using MacroTools

macro foo(expr)
    def = MacroTools.splitdef(expr)

    make_pair(arg) = :($(Meta.quot(arg)) => $arg)
    def[:body] = quote
        d = Dict($(map(make_pair, def[:args])...))
        println(d)
        $(def[:body])
    end

    MacroTools.combinedef(def)
end
关于此代码的一些备注和解释:

  • 试图重写/修改函数定义的宏可以从中使用
    splitdef
    combinedef
    函数中获得很大的好处。在全球范围内,拟议的宏观经济政策包括3个阶段:
  • 将功能定义拆分为单独的部分
  • 在函数体的开头插入所需的代码
  • 将所有零件(包括修改后的车身)重新组合成合法的功能定义
  • 包含函数参数的字典由以下关键成分构成:
    • make_pair
      接受给定的变量名(作为符号,例如
      :a
      ),并返回一个对该变量对进行求值的表达式
      :a=>a
    • 然后将此
      make_pair
      函数映射到来自(分解的)函数定义的所有参数,以构建参数对数组
    • 最后,这个数组被飞溅到
      Dict
      构造函数中
我们可以检查此示例函数定义是否扩展为预期代码:

julia> Base.remove_linenums!(@macroexpand @foo function bar(a,b,c)
           a + b + c
       end)
:(function Main.bar(var"#26#a", var"#27#b", var"#28#c"; )
      var"#25#d" = Main.Dict(:a => var"#26#a", :b => var"#27#b", :c => var"#28#c")
      Main.println(var"#25#d")
      begin
          var"#26#a" + var"#27#b" + var"#28#c"
      end
  end)
。。。更一般地说,在运行时,一切都按预期运行:

julia> @foo function bar(a, b, c)
           a + b + b
       end
bar (generic function with 1 method)

julia> bar(1, 2, 3)
Dict(:a => 1,:b => 2,:c => 3)
5
julia> @foo function bar(a, b, c)
           a + b + b
       end
bar (generic function with 1 method)

julia> bar(1, 2, 3)
Dict(:a => 1,:b => 2,:c => 3)
5