重复应用特定次数的功能

时间:2016-10-06 12:13:04

标签: function julia

如果你有一个功能,是否有一种简单或内置的方式来应用它n次,或者直到结果是特定的。因此,例如,如果您要将sqrt函数应用4次,效果为:

julia> sqrt(sqrt(sqrt(sqrt(11231))))
1.791229164345863
你可以输入类似的内容:

repeatf(sqrt, 11231, 4)

4 个答案:

答案 0 :(得分:5)

[编辑:在没有迭代器的情况下查看底部的简单解决方案,不过我建议使用它和包中的所有有用功能]

使用Iterators包,以下可能是一个解决方案:

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

iterate执行组合逻辑(对于描述,请在REPL上执行?iterate)。较新版本的Iterators(仍然没有标记)有一个名为nth的函数,这会使这更简单:

nth(iterate(sqrt,11231.0),5)

作为旁注,可以很好地使用名称定义(x,y)->y匿名函数,因为它可能经常与reduce一起使用,如下所示:

first(x,y) = x
second(x,y) = y

现在,

julia> reduce(second,take(iterate(sqrt,11231.0),5))
1.791229164345863

的工作原理。此外,没有递归(需要堆栈分配和浪费),以及与迭代深度成比例的分配,这可能更有效,特别是对于比5更高的迭代值。

没有Iterators包,使用foldl的简单解决方案是

julia> foldl((x,y)->sqrt(x),11231.0,1:4)
1.791229164345863

和以前一样,简化操作是关键,这次它应用sqrt但忽略迭代器值,迭代器值仅用于设置函数的应用次数(可能是与{{不同的迭代器或向量)可以在应用程序中使用1}}以提高代码的可读性。

答案 1 :(得分:4)

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

<table>
   <tr ng-repeat="x in jobs" ng-class-odd="'odd'" ng-class-even="'even'">
     <td style="width: 247px;">
        <input type="checkbox" ng-model="checked">
     </td>
     <td style="width: 247px;">{{ x.Name }}</td>
     <td style="width: 247px;">{{ x.Id }}</td>
   </tr>
</table>

<button ng-click="myFunc()" ng-disabled="!isAtLeastARowChecked">Cancel</button>


$scope.$watchCollection("jobs", function(newVal, oldVal){
    isAtLeastARowChecked = (newVal && newVal.length > 0);
});

也是,甚至更舒适

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

julia> repeatf(sqrt, 11321, 4)
 106.40018796975878

用于具有多个争论的函数

答案 2 :(得分:4)

我很乐意定义^运算符来处理FunctionInt s

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

正如@DNF指出的那样,因为julia没有Tail Call Optimisatation, 迭代地做这个更好;

```

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

热身后:

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)

在这种情况下,开销并不是太糟糕,但最后StackOverflowError是一个踢球者。

答案 3 :(得分:2)

function apply(f, x, n=1)
    for _ in 1:n
        x = f(x)
    end
    return x
end