Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby-on-rails-4/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Julia元编程:数学级数的函数_Julia - Fatal编程技术网

Julia元编程:数学级数的函数

Julia元编程:数学级数的函数,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 因此,这将构建

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

main.jl

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