我正在研究Julia函数,该函数在闭包内部构造具有多个方法的函数并将其返回。为了简化(实际构造涉及多个非平凡的自定义类型),它看起来像这样:
function constructF(g::Function, n::Int)
v = [g]
for i in 2:n
gi(x) = ForwardDiff.derivative(v[i - 1], x)
v = vcat(v, gi)
end
for T in (Int, Float64) # two types but possibly more
function f(x::T)
acc = T(0)
for i in 1:n
acc += v[i](x)^i
end
acc
end
end
return f
end
从Julia 1.1.1开始不支持这种代码,这给了我
ERROR: LoadError: syntax: local variable T cannot be used in closure declaration
Stacktrace:
[1] include(::String) at ./client.jl:403
[2] top-level scope at none:0
in expression starting at /home/me/code/lang/julia/test.jl:3
替代方法如下,但导致代码重复。
function constructF(n::Int)
v = [g]
for i in 2:n
gi(x) = ForwardDiff.derivative(v[i - 1], x)
v = vcat(v, gi)
end
function f(x::Int)
acc = Int(0)
for i in 1:n
acc += v[i](x)^i
end
acc
end
function f(x::Float64)
acc = Float64(0)
for i in 1:n
acc += v[i](x)^i
end
acc
end
# ....
return f
end
有没有更好的方法来写这个?我已经研究了元编程,但是文档看起来不直观,我不确定如何在这里应用它。
答案 0 :(得分:1)
我刚刚回答了我自己的问题。通过一些基本的元编程,我可以做到:
function constructF(g::Function, n::Int)
v = [g]
for i in 2:n
gi(x) = ForwardDiff.derivative(v[i - 1], x)
v = vcat(v, gi)
end
for T in (:Int, :Float64)
@eval function f(x::$T)
acc = $T(0)
for i in 1:$n
acc += $v[i](x)^i
end
acc
end
end
return f
end
创建一个Julia表达式,并使用Int,Float64等每种类型对其求值...
答案 1 :(得分:0)
您遇到的是一个答案,但不是朱利安的答案。
function constructF(g::Function, n::Int)
v = [g]
for i in 2:n
gi(x) = ForwardDiff.derivative(v[i - 1], x)
v = vcat(v, gi)
end
function f(x::T<:Number)
acc = zero(T)
for i in 1:n
acc += v[i](x)^i
end
acc
end
return f
end
如果您担心不定义特定方法会更慢,那么您还不了解Julia编译器的强大功能。当您通过输入调用它时,它将神奇地生成针对特定类型的优化代码。