重复应用功能特定次数

day*_*ter 6 function julia

如果您具有某个功能,是否可以通过简单或内置的方式来应用该功能n,或者直到结果特定为止。因此,例如,如果您要应用该sqrt功能4次,效果如下:

julia> sqrt(sqrt(sqrt(sqrt(11231))))
1.791229164345863
Run Code Online (Sandbox Code Playgroud)

您可以输入以下内容:

repeatf(sqrt, 11231, 4)
Run Code Online (Sandbox Code Playgroud)

Lyn*_*ite 7

我很喜欢定义该^运算符来处理Functions 和Ints

julia> (^)(f::Function, i::Int) = i==1 ? f : x->(f^(i-1))(f(x))
^ (generic function with 1 method)

julia> (sqrt^1)(2)
1.4142135623730951

julia> (sqrt^2)(2)
1.189207115002721

julia> (sqrt^3)(2)
1.0905077326652577
Run Code Online (Sandbox Code Playgroud)

正如@DNF 指出的那样,因为 julia 没有尾调用优化,所以最好迭代地执行此操作;


    julia> function (?)(f::Function, i::Int)
               function inner(x)
                  for ii in i:-1:1
                     x=f(x)
                  end
               x
               end
           end


After warmup:

    julia> @time((sqrt ? 1_000)(20e300)) #Iterative
      0.000018 seconds (6 allocations: 192 bytes)
    1.0
    
    julia> @time((sqrt ^ 1_000)(20e300)) #Recursive
      0.000522 seconds (2.00 k allocations: 31.391 KB)
    1.0
    
    #########
    
    julia> @time((sqrt ? 10_000)(20e300)) #Iterative
      0.000091 seconds (6 allocations: 192 bytes)
    1.0
    
    
    julia> @time((sqrt ^ 10_000)(20e300)) #Recursive
      0.003784 seconds (20.00 k allocations: 312.641 KB)
    1.0
    
    #########
    
    julia> @time((sqrt ? 30_000)(20e300)) # Iterative
      0.000224 seconds (6 allocations: 192 bytes)
    1.0

    julia> @time((sqrt ^ 30_000)(20e300)) #Recursive
      0.008128 seconds (60.00 k allocations: 937.641 KB)
    1.0
    
    
    #############
   
    julia> @time((sqrt ? 100_000)(20e300)) #Iterative
      0.000393 seconds (6 allocations: 192 bytes)
    1.0

    julia> @time((sqrt ^ 100_000)(20e300)) #Recursive
    ERROR: StackOverflowError:
     in (::##5#6{Base.#sqrt,Int64})(::Float64) at ./REPL[1]:1 (repeats 26667 times)



The overhead isn't too bad in this case, but that `StackOverflowError` at the end is a kicker.
Run Code Online (Sandbox Code Playgroud)


ise*_*arn 5

我不知道这样的功能,但你可以使用这个

julia> repeatf(f, x, n) = n > 1 ? f(repeatf(f, x, n-1)) : f(x)

julia> repeatf(sqrt, 11321, 4)
 106.40018796975878
Run Code Online (Sandbox Code Playgroud)

而且,甚至更舒适

repeatf(n, f, x...) = n > 1 ? f(repeatf(n-1, f, x...)...) : f(x...)
Run Code Online (Sandbox Code Playgroud)

具有多个论点的功能


Dan*_*etz 5

[编辑:不带迭代器的简单解决方案,请参阅底部,尽管我建议使用它以及包中的所有有用功能]

使用Iterators程序包,可能是以下解决方案:

julia> using Iterators   # install with Pkg.add("Iterators")
julia> reduce((x,y)->y,take(iterate(sqrt,11231.0),5))
1.791229164345863
Run Code Online (Sandbox Code Playgroud)

iterate进行合成逻辑(?iterate在REPL上进行描述)。较新的Iterators版本(仍未标记)具有称为的函数nth,这将使此过程更加简单:

nth(iterate(sqrt,11231.0),5)
Run Code Online (Sandbox Code Playgroud)

附带说明一下,(x,y)->y匿名函数可以很好地定义一个名称,因为它可能经常用于reduce

first(x,y) = x
second(x,y) = y
Run Code Online (Sandbox Code Playgroud)

现在,

julia> reduce(second,take(iterate(sqrt,11231.0),5))
1.791229164345863
Run Code Online (Sandbox Code Playgroud)

作品。同样,如果没有递归(这需要堆栈分配和浪费),并且分配与迭代深度成比例,则这样做可能会更有效,尤其是对于高于5的迭代值。

如果没有Iterators包,使用一个简单的解决方案foldl

julia> foldl((x,y)->sqrt(x),11231.0,1:4)
1.791229164345863
Run Code Online (Sandbox Code Playgroud)

和以前一样,归约运算是关键,这一次它适用,sqrt但是忽略了迭代器值,这些迭代器值仅用于设置应用函数的次数(也许1:4与应用程序中使用的迭代器或向量不同,以更好地读取)。码)