Julia 元编程:数学系列函数

nom*_*ize 3 julia

我正在尝试构建一个函数,该函数将输出要分配给新内存函数的表达式。我可能误解了元编程的能力,但是,我正在尝试构建一个函数来生成数学系列并将其分配给一个函数,例如:

在此处输入图片说明

主文件

function series(iter)
    S = ""
    for i in 1:iter
        a = "x^$i + "
        S = S*a
    end
    return chop(S, tail=3)
end
Run Code Online (Sandbox Code Playgroud)

所以,这将构建模式,我暂时在 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
Run Code Online (Sandbox Code Playgroud)

显然 eval 在这种情况下不是我要找的,但是,我可以使用另一个函数吗?或者,这不是在 Julia 中完成任务的可行方法吗?

phi*_*ler 5

你得到的实际错误与元编程无关,但事实上你正在重新分配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
Run Code Online (Sandbox Code Playgroud)

它只是不喜欢那样。以不同方式调用这些变量中的任何一个。

现在是概念问题。首先,你在这里做的不是 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)
Run Code Online (Sandbox Code Playgroud)

这利用了+属于在重复应用程序中自动收集的表达式类的事实。

其次,你没有eval在适当的地方打电话。我假设你的意思是“给我 的功能x,身体是series(4)返回的东西”。现在,虽然以下工作:

julia> f3(x) = eval(series(4))
f3 (generic function with 1 method)

julia> f3(2)
30
Run Code Online (Sandbox Code Playgroud)

这并不理想,因为每次调用函数时都会重新编译主体。如果你做类似的事情,最好在函数定义时将代码扩展到主体中:

julia> @eval f2(x) = $(series(4))
f2 (generic function with 1 method)

julia> f2(2)
30
Run Code Online (Sandbox Code Playgroud)

你只需要在这里注意卫生。一切都取决于这样一个事实,即您知道生成的主体是根据 制定的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
Run Code Online (Sandbox Code Playgroud)

输出中没有剩余的自由变量。

最后,正如评论中所指出的,evalpolyBase 中有一个函数(和相应的宏)可以概括您的用例。请注意,此功能对使用代码生成-它采用了精心设计的生成的函数,其与在代码是优化结果组合通常等于宏生成的代码。