首页 文章

朱莉娅:一起添加匿名功能

提问于
浏览
8

如果我定义一些匿名函数 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 回答

  • 5

    您可以使用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
    

    Explanation

    let关键字允许您创建具有本地范围的块,并将块中的最后一个语句返回其调用范围 . (与begin关键字形成对比,例如,它没有引入新的范围) .

    如果将"assignments"序列传递给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变量,你可以改为: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 . 我猜想利文斯通博士?

  • 7

    使用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,但我还没有使用它) .

  • 1

    这个:

    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)
    

    EDIT

    我现在看到来自MATLAB,你期望语法意味着别的东西 . 您在几乎所有语言中编写的内容都是递归调用,您不需要 . 你想要的是这样的:

    concatFuncs => f1,f2 -> (x->f1(x)+f2(x))
    

    这段代码将接受任何函数接受 x 并在结果调用之间生成 . 这适用于'+'使用的任何内容 . 所以:

    summed = concatFuncs(a,b)
    

    是你需要的功能 .

相关问题