如果我定义一些匿名函数 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
...
但是,这会失败并返回一些错误 . 我'm assuming it'因为调用新的 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)
有没有办法解决?
3 回答
您可以使用the let keyword完成您正在寻找的内容:
Explanation
let关键字允许您创建具有本地范围的块,并将块中的最后一个语句返回其调用范围 . (与begin关键字形成对比,例如,它没有引入新的范围) .
如果将"assignments"序列传递给let关键字,则这些变量将成为块的本地变量(因此,允许您重新使用工作空间中已存在的变量名称) . 声明
let a = a
是完全有效的,意思是“创建一个局部变量a
,它是从外部范围的a
变量初始化的”---但是如果我们想要非常清楚,我们可以这样写它:然后再次,如果你愿意使用a_old变量,你可以改为:i = 1:5; a_old = a; a = x-> a_old(x)b(x);结束
let
是一个非常有用的关键字:它对于创建现场闭包非常方便;事实上,这正是我们在这里所做的:我们已经返回了一个闭包,其中“局部变量a
”基本上变成了一个闭合变量 .PS . 由于提到了matlab,当你在matlab中评估a = @(x)a(x)b(x)时你正在做的事实上是创建一个闭包 . 在matlab中,您可以使用functions命令检查所有已关闭的变量(即闭包的“工作空间”)
PPS . 我猜想利文斯通博士?
使用Polynomials包可能是一种方式 . 这会:
这有效的原因是因为你想要的行为本质上是对函数的符号操作 . Julia不是这样工作的(它是一个编译器 - 或者是提前编译(AOT)编译器),但它很灵活 . 如果需要比多项式更高级的函数,可能有一个符号数学包会有所帮助(有SymPy,但我还没有使用它) .
这个:
是一个没有停止条件的递归调用 . 它与朱莉娅无关 . 一旦定义了这个,之前的定义(
x^2
)就被覆盖了,并且对于堆栈或结果没有任何意义 . 它没有尝试做的是:2 * 2甚至不会被替换,我只是写得很清楚 . 你可能想要定义
EDIT
我现在看到来自MATLAB,你期望语法意味着别的东西 . 您在几乎所有语言中编写的内容都是递归调用,您不需要 . 你想要的是这样的:
这段代码将接受任何函数接受
x
并在结果调用之间生成 . 这适用于'+'使用的任何内容 . 所以:是你需要的功能 .