Julia元编程:数学级数的函数
我正在尝试构建一个函数,该函数将输出一个表达式以分配给一个新的内存函数。我可能误解了元编程的功能,但我试图构建一个函数,生成一个数学系列并将其分配给一个函数,例如: main.jlJulia元编程:数学级数的函数,julia,Julia,我正在尝试构建一个函数,该函数将输出一个表达式以分配给一个新的内存函数。我可能误解了元编程的功能,但我试图构建一个函数,生成一个数学系列并将其分配给一个函数,例如: main.jl function series(iter) S = "" for i in 1:iter a = "x^$i + " S = S*a end return chop(S, tail=3) end 因此,这将构建
function series(iter)
S = ""
for i in 1:iter
a = "x^$i + "
S = S*a
end
return chop(S, tail=3)
end
因此,这将构建模式,我暂时在repl中使用它:
julia> a = Meta.parse(series(4))
:(x ^ 1 + x ^ 2 + x ^ 3 + x ^ 4)
julia> f =eval(Meta.parse(series(4)))
120
julia> f(x) =eval(Meta.parse(series(4)))
ERROR: cannot define function f; it already has a value
显然,eval不是我在本例中所要寻找的,但是,是否还有其他功能可以使用?或者,这不是在Julia中完成任务的可行方法吗?您得到的实际错误与元编程无关,而是与您正在重新分配
f
这一事实有关,该值在以下情况下被分配:
julia> f = 10
10
julia> f(x) = x + 1
ERROR: cannot define function f; it already has a value
Stacktrace:
[1] top-level scope at none:0
[2] top-level scope at REPL[2]:1
它就是不喜欢那样。以不同的方式调用这两个变量中的任何一个
现在是概念问题。首先,在Julia中,您在这里所做的不是“正确的”元编程:为什么要处理字符串和解析呢?您可以直接处理表达式:
julia> function series(N)
S = Expr(:call, :+)
for i in 1:N
push!(S.args, :(x ^ $i))
end
return S
end
series (generic function with 1 method)
julia> series(3)
:(x ^ 1 + x ^ 2 + x ^ 3)
这利用了+
属于在重复应用程序中自动收集的表达式类这一事实
其次,不要在适当的位置调用eval
。我想你的意思是“给我x
的函数,主体是系列(4)
返回的内容”。现在,当以下各项起作用时:
julia> f3(x) = eval(series(4))
f3 (generic function with 1 method)
julia> f3(2)
30
这并不理想,因为每次调用函数时都要重新编译主体。如果您这样做,最好在函数定义中将代码展开一次到主体中:
julia> @eval f2(x) = $(series(4))
f2 (generic function with 1 method)
julia> f2(2)
30
你只需要注意这里的卫生。所有这些都取决于这样一个事实,即您知道生成的主体是按照x
进行公式化的,并且函数参数与此匹配。在我看来,实现您想法的最朱利安的方式是通过宏观:
julia> macro series(N::Int, x)
S = Expr(:call, :+)
for i in 1:N
push!(S.args, :($x ^ $i))
end
return S
end
@series (macro with 1 method)
julia> @macroexpand @series(4, 2)
:(2 ^ 1 + 2 ^ 2 + 2 ^ 3 + 2 ^ 4)
julia> @series(4, 2)
30
输出中没有剩余的自由变量
最后,正如注释中所指出的,Base中有一个函数(和相应的宏),它概括了您的用例。请注意,此函数不使用代码生成--它使用精心设计的生成函数,与优化相结合,生成的代码通常等于宏生成的代码。另一个优雅的选择是使用Julia的多重分派机制,并根据类型而不是值分派生成的代码
@generated function series2(p::Val{N}, x) where N
S = Expr(:call, :+)
for i in 1:N
push!(S.args, :(x ^ $i))
end
return S
end
用法
这项任务可以通过理解来完成。我需要RTFM
你知道evalpoly吗?谢谢,我不知道。但是,我希望将其抽象出来以匹配其他模式。您知道Lazy.jl包吗?哇!谢谢你提供的细节!我对元/宏显然是新手,这真的很有帮助。你完全正确!我忘了
Val
。现在我更新了Tuple
并将其更改为Val
julia> series2(Val(20), 150.5)
3.5778761722367333e43
julia> series2(Val{20}(), 150.5)
3.5778761722367333e43