我想自动构建许多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"
答案 0 :(得分:6)
您应该从宏返回一个表达式。要使代码成为表达式,请使用:(....)
或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
答案 1 :(得分:0)
我从麻省理工学院的Steven G. Johnson那里学到了如何从阅读源代码到非常好的DecFP.jl包(https://github.com/stevengj/DecFP.jl)。
它使用带有@eval
宏的简单循环来生成C库的所有包装器。