【问题标题】:Metaprogramming Julia functions with args and keyword args使用 args 和关键字 args 元编程 Julia 函数
【发布时间】:2016-09-10 20:02:50
【问题描述】:

我想自动构建许多 Julia 函数(元编程)来包装一个库。

这是我要生成的函数:

function myfunc(a::Array{Float64,1}, b::Array{Float64,1}; x=Int64(1), y=Float64(2))
    x + y
end

这里是我想用来生成这样一个函数的函数的参数。

funcname = :my_func
args = (:a, :b)
args_typ = (Array{Float64,1}, Array{Float64,1})
kw_args = (:x, :y)
kw_defval = (1, 2)
kw_typ = (Int64, Float64)

我对 Julia 宏感到不舒服,http://docs.julialang.org/en/release-0.4/manual/metaprogramming/ 对我没有多大帮助。

我也希望能够显示函数(生成)代码。

我的第一个想法(不是很自动化)是

macro GEN_FUNC(funcname)
    function $funcname(a, b, x=1, y=2)
        return x
    end
end

但它提高了

ERROR: syntax: invalid method name "$funcname"

【问题讨论】:

    标签: function metaprogramming julia


    【解决方案1】:

    您应该从宏中返回一个表达式。要使代码成为表达式,请使用:(....)quote ... end 装饰您的代码。此外,$ 仅对表达式和字符串有效。最后,宏存在卫生问题。为了保持$funcname 完整,您需要esc 围绕它。这是更正的代码

    julia> macro GEN_FUNC(funcname)  
               fname=esc(funcname)  
               quote  
                   function $fname(a, b, x=1, y=2)  
                       return x  
                   end  
               end  
           end  
    
    julia> macroexpand(:(@GEN_FUNC testing))  
    quote  # none, line 4:  
        function testing(#21#a,#22#b,#23#x=1,#24#y=2) # none, line 5:  
            return #23#x  
        end  
    end
    

    更新:这是手动构造 myfunc 的方法(提示:我用 quote ... end 将它变成了一个表达式并从中作弊)

    julia> f_body=:(x+y)
    :(x + y)
    
    julia> f_parameters=Expr(:parameters, Expr(:kw,:x,Int64(1)), Expr(:kw,:y,Float64(2)))
    :($(Expr(:parameters, :(x=1), :(y=2.0))))
    
    julia> f_call=Expr(:call,:myfunc,f_parameters,:(a::Array{Float64,1}),:(b::Array{Float64,1}))
    :(myfunc(a::Array{Float64,1},b::Array{Float64,1}; x=1,y=2.0))
    
    julia> f_declare=Expr(:function,f_call,f_body)
    :(function myfunc(a::Array{Float64,1},b::Array{Float64,1}; x=1,y=2.0)
            x + y
        end)
    
    julia> eval(f_declare)
    myfunc (generic function with 1 method)
    
    julia> myfunc(2,3)
    ERROR: MethodError: `myfunc` has no method matching myfunc(::Int64, ::Int64)
    
    julia> myfunc([2.],[3.])
    3.0
    
    julia> myfunc([2.],[3.];x=4,y=8.)
    12.0
    

    【讨论】:

    • 如何自动生成参数?
    • 我仍然面临从元组构建 f_parametersf_call 的问题。任何帮助都会很棒。
    【解决方案2】:

    我通过阅读 MIT 的 Steven G. Johnson 编写的非常好的 DecFP.jl 包 (https://github.com/stevengj/DecFP.jl) 的源代码来学习如何做到这一点。

    它使用带有 @eval 宏的简单循环来生成 C 库的所有包装器。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-02-19
      • 2023-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-28
      • 2012-12-09
      相关资源
      最近更新 更多