Julia:一起添加匿名函数
Julia: adding anonymous functions together
如果我将一些匿名函数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
...
但是,这失败了并且 returns 出现了一些错误。我假设这是因为调用新的 a(x)
被解释为:a(2) = 2 -> x^2 + x^2 + ... + x^2 + 2x
julia> a(2)
ERROR: WhosebugError:
in (::##35#36)(::Int64) at ./REPL[115]:0
in (::##35#36)(::Int64) at ./REPL[115]:1 (repeats 26666 times)
有什么办法解决这个问题吗?
这个:
a = x -> a(x) + b(x)
是一个没有停止条件的递归调用。这与朱莉娅无关。一旦您定义它,先前的定义 (x^2
) 就会被覆盖,并且与堆栈或您的结果无关。它不存在了。您要做的是:
a(2) = a(2)+2*2 = (a(2)+2*2)+2*2 = ((a(2)+2*2)+2*2)+2*2 = ...
等2*2 甚至不会被替换,我只是为了清楚而写的。你可能想定义
c = x -> a(x) + b(x)
编辑
我现在看到来自 MATLAB 的语法有其他含义。您用几乎所有语言编写的都是递归调用,这是您不想要的。你想要的是这样的:
concatFuncs => f1,f2 -> (x->f1(x)+f2(x))
这段代码将采用任何接受 x
的函数,并在结果调用之间生成 +。这将适用于“+”适用的任何东西。所以:
summed = concatFuncs(a,b)
是您需要的功能。
使用 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,但我没用过)。
您可以使用 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
keyword allows you to create a block with local scope, and return the last statement in the block back to its caller scope. (contrast that with the begin
关键字,它不会引入新的作用域)。
如果将 "assignments" 的序列传递给 let 关键字,这些变量将成为块的局部变量(因此,允许您重新使用工作区中已存在的变量名称)。声明 let a = a
是完全有效的,意思是 "create a local variable a
which is initialised from the a
variable of the outer scope" --- 尽管如果我们想 真正 清楚,我们可以这样写:
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
是一个非常有用的关键字:它对于创建现场闭包非常方便;事实上,这正是我们在这里所做的:我们返回了一个闭包,其中 "local variable a
" 本质上变成了一个封闭变量。
PS。由于提到了 matlab,所以当您在 matlab 中评估 a = @ (x) a(x) + b(x)
时,您所做的实际上是创建一个闭包。在 matlab 中,您可以使用 functions
命令
检查所有封闭变量(即闭包的 'workspace')
PPS。 利文斯通博士,我猜?
如果我将一些匿名函数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
...
但是,这失败了并且 returns 出现了一些错误。我假设这是因为调用新的 a(x)
被解释为:a(2) = 2 -> x^2 + x^2 + ... + x^2 + 2x
julia> a(2)
ERROR: WhosebugError:
in (::##35#36)(::Int64) at ./REPL[115]:0
in (::##35#36)(::Int64) at ./REPL[115]:1 (repeats 26666 times)
有什么办法解决这个问题吗?
这个:
a = x -> a(x) + b(x)
是一个没有停止条件的递归调用。这与朱莉娅无关。一旦您定义它,先前的定义 (x^2
) 就会被覆盖,并且与堆栈或您的结果无关。它不存在了。您要做的是:
a(2) = a(2)+2*2 = (a(2)+2*2)+2*2 = ((a(2)+2*2)+2*2)+2*2 = ...
等2*2 甚至不会被替换,我只是为了清楚而写的。你可能想定义
c = x -> a(x) + b(x)
编辑
我现在看到来自 MATLAB 的语法有其他含义。您用几乎所有语言编写的都是递归调用,这是您不想要的。你想要的是这样的:
concatFuncs => f1,f2 -> (x->f1(x)+f2(x))
这段代码将采用任何接受 x
的函数,并在结果调用之间生成 +。这将适用于“+”适用的任何东西。所以:
summed = concatFuncs(a,b)
是您需要的功能。
使用 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,但我没用过)。
您可以使用 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
keyword allows you to create a block with local scope, and return the last statement in the block back to its caller scope. (contrast that with the begin
关键字,它不会引入新的作用域)。
如果将 "assignments" 的序列传递给 let 关键字,这些变量将成为块的局部变量(因此,允许您重新使用工作区中已存在的变量名称)。声明 let a = a
是完全有效的,意思是 "create a local variable a
which is initialised from the a
variable of the outer scope" --- 尽管如果我们想 真正 清楚,我们可以这样写:
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
是一个非常有用的关键字:它对于创建现场闭包非常方便;事实上,这正是我们在这里所做的:我们返回了一个闭包,其中 "local variable a
" 本质上变成了一个封闭变量。
PS。由于提到了 matlab,所以当您在 matlab 中评估 a = @ (x) a(x) + b(x)
时,您所做的实际上是创建一个闭包。在 matlab 中,您可以使用 functions
命令
PPS。 利文斯通博士,我猜?