Recursion 在递归函数内部定义函数与在F外部定义函数相比,有哪些性能副作用#

Recursion 在递归函数内部定义函数与在F外部定义函数相比,有哪些性能副作用#,recursion,f#,let,Recursion,F#,Let,如果您有一个依赖于其他函数的递归函数,那么实现它的首选方法是什么 1) 在递归函数之外 let doSomething n = ... let rec doSomethingElse x = match x with | yourDone -> ... | yourNotDone -> doSomethingElse (doSomething x) let rec doSomethingElse x = let doSomething n = ...

如果您有一个依赖于其他函数的递归函数,那么实现它的首选方法是什么

1) 在递归函数之外

let doSomething n = ...
let rec doSomethingElse x =
    match x with
    | yourDone -> ...
    | yourNotDone -> doSomethingElse (doSomething x)
let rec doSomethingElse x =
    let doSomething n = ...
    match x with
    | yourDone -> ...
    | yourNotDone -> doSomethingElse (doSomething x)
let doSomethingElse x =
    let doSomething n = ...
    let innerDoSomethingElse =
        match x with
        | yourDone -> ...
        | yourNotDone -> innerDoSomethingElse (doSomething x)
2) 递归函数内部

let doSomething n = ...
let rec doSomethingElse x =
    match x with
    | yourDone -> ...
    | yourNotDone -> doSomethingElse (doSomething x)
let rec doSomethingElse x =
    let doSomething n = ...
    match x with
    | yourDone -> ...
    | yourNotDone -> doSomethingElse (doSomething x)
let doSomethingElse x =
    let doSomething n = ...
    let innerDoSomethingElse =
        match x with
        | yourDone -> ...
        | yourNotDone -> innerDoSomethingElse (doSomething x)
3) 将两者封装在第三个函数中

let doSomething n = ...
let rec doSomethingElse x =
    match x with
    | yourDone -> ...
    | yourNotDone -> doSomethingElse (doSomething x)
let rec doSomethingElse x =
    let doSomething n = ...
    match x with
    | yourDone -> ...
    | yourNotDone -> doSomethingElse (doSomething x)
let doSomethingElse x =
    let doSomething n = ...
    let innerDoSomethingElse =
        match x with
        | yourDone -> ...
        | yourNotDone -> innerDoSomethingElse (doSomething x)
4) 还有更好的吗

module Test =

    let f x = 
      let add a b = a + b //inner function
      add x 1

    let f2 x =
      let add a = a + x //inner function with capture, i.e., closure
      add x

    let outerAdd a b = a + b

    let f3 x =
      outerAdd x 1
翻译为:

[CompilationMapping(SourceConstructFlags.Module)]
public static class Test {

    public static int f(int x) {
        FSharpFunc<int, FSharpFunc<int, int>> add = new add@4();
        return FSharpFunc<int, int>.InvokeFast<int>(add, x, 1);
    }

    public static int f2(int x) {
        FSharpFunc<int, int> add = new add@8-1(x);
        return add.Invoke(x);
    }

    public static int f3(int x) {
        return outerAdd(x, 1);
    }

    [CompilationArgumentCounts(new int[] { 1, 1 })]
    public static int outerAdd(int a, int b) {
        return (a + b);
    }

    [Serializable]
    internal class add@4 : OptimizedClosures.FSharpFunc<int, int, int> {
        internal add@4() { }

        public override int Invoke(int a, int b) {
            return (a + b);
        }
    }

    [Serializable]
    internal class add@8-1 : FSharpFunc<int, int> {
        public int x;

        internal add@8-1(int x) {
            this.x = x;
        }

        public override int Invoke(int a) {
            return (a + this.x);
        }
    }
}
[编译映射(SourceConstructFlags.Module)]
公共静态类测试{
公共静态整数f(整数x){
FSharpFunc add=新建add@4();
返回FSharpFunc.InvokeFast(add,x,1);
}
公共静态int f2(int x){
FSharpFunc add=新建add@8-1(x);
返回add.Invoke(x);
}
公共静态int f3(int x){
返回外置(x,1);
}
[编译参数计数(新int[]{1,1}]
公共静态int OUTRADD(int a,int b){
返回(a+b);
}
[可序列化]
内部类add@4:OptimizedClosures.FSharpFunc{
内部的add@4() { }
公共重写int调用(int a,int b){
返回(a+b);
}
}
[可序列化]
内部类add@8-1:FSharpFunc{
公共int x;
内部的add@8-1(整数x){
这个.x=x;
}
公共重写int调用(int a){
返回值(a+this.x);
}
}
}
内部函数的唯一额外成本是新创建一个
FSharpFunc
的实例,这似乎可以忽略不计


除非您对性能非常敏感,否则我会选择最有意义的范围,即尽可能窄的范围。

答案可能可以从您的代码片段中推断出来,但您确实应该把它拼出来。请参见最后一句。我没有时间对其进行基准测试,但我提到了唯一值得注意的区别。创建
FSharpFunc
可能会因为大量使用代码而损害性能,但在大多数情况下,这并不重要。为什么投票结果接近?这似乎是一个非常好/合理的问题。