如果我将一些匿名函数a(x)
和b(x)
定义为
a = x -> x^2
b = x -> 2x
将递归问题添加到一起会有所帮助,比如在某个循环的持续时间内:
for i=1:5
a = x -> a(x) + b(x)
end
其中的目标是将每个循环迭代内部表示为
a = x -> x^2 + 2x
a = x -> x^2 + 2x + x^2 + 2x
a = x -> x^2 + 2x + x^2 + 2x + x^2 + 2x
...
但是,这会失败并返回一些错误。我假设是因为调用新的a(x)
被解释为:a(2) = 2 -> x^2 + x^2 + ... + x^2 + 2x
julia> a(2)
ERROR: StackOverflowError:
in (::##35#36)(::Int64) at ./REPL[115]:0
in (::##35#36)(::Int64) at ./REPL[115]:1 (repeats 26666 times)
这有什么办法吗?
答案 0 :(得分:7)
您可以使用the let
keyword完成您正在寻找的内容:
a = x -> x^2
b = x -> 2x
for i=1:5
a = let a = a; x -> a(x) + b(x); end
end
a(2) # returns 24
<强>解释强>
let
关键字允许您创建具有本地范围的块,并将块中的最后一个语句返回其调用范围。 (与例如begin
关键字形成鲜明对比,不引入新范围)。
如果将一系列“赋值”传递给let关键字,则这些变量将成为块的本地变量(因此,允许您重新使用工作空间中已存在的变量名称)。声明let a = a
完全有效,意味着“创建一个局部变量a
,它是从外部范围的a
变量初始化的”---但是如果我们想要真的清楚,我们可以这样写它:
for i=1:5
a = let a_old = a
x -> a_old(x) + b(x);
end
end
<小时/> 然后再次,如果你愿意使用
a_old
变量,你可能只是这样做了:for i=1:5; a_old = a; a = x-> a_old(x) + b(x); end
子>
let
是一个非常有用的关键字:它非常便于创建现场闭包;事实上,这正是我们在这里所做的:我们已经返回了一个闭包,其中“局部变量a
”基本上变成了一个闭合变量。
<子> PS。由于提到了matlab,当你在matlab中评估a = @ (x) a(x) + b(x)
时你正在做的事实上是创建一个闭包。在matlab中,您可以使用functions
命令检查所有已关闭的变量(即闭包的“工作空间”)
<子> PPS。 利文斯通博士,我猜?
答案 1 :(得分:5)
使用Polynomials包可能是一种方式。这将是:
julia> using Polynomials # install with Pkg.add("Polynomials")
julia> x = Poly([0,1])
Poly(x)
julia> a = x^2
Poly(x^2)
julia> b = 2x
Poly(2*x)
julia> a = a+b
Poly(2*x + x^2)
julia> a(2.0)
8.0
这是有效的原因是因为你想要的行为本质上是对函数的符号操作。 Julia不是这样工作的(它是编译器 - 或者提前编译(AOT)编译器),但它很灵活。如果需要比多项式更高级的函数,可能有一个符号数学包会有所帮助(有SymPy,但我还没有使用它)。
答案 2 :(得分:1)
此:
x^2
是一个没有停止条件的递归调用。它与朱莉娅无关。一旦定义了这个,之前的定义(a(2) = a(2)+2*2 = (a(2)+2*2)+2*2 = ((a(2)+2*2)+2*2)+2*2 = ...
)就被覆盖了,并且对于堆栈或结果没有任何意义。它不再存在。你要做的是:
c = x -> a(x) + b(x)
等。 2 * 2甚至不会被替换,我只是写得很清楚。您可能想要定义
concatFuncs => f1,f2 -> (x->f1(x)+f2(x))
修改强>
我现在看到来自MATLAB,你期望语法意味着别的东西。您在几乎所有语言中编写的内容都是递归调用,您不需要。你想要的是:
x
这段代码将接受summed = concatFuncs(a,b)
的任何函数,并在结果调用之间生成一个+。这适用于'+'使用的任何内容。所以:
app/design/frontend/base/default/layout/poll.xml
是您需要的功能。