再帰関数内での関数の定義とF#での外部とのパフォーマンスの副作用は何ですか?

あなたが他の関数に依存する再帰関数を持っているのであれば、それを実装するのに好ましい方法は何ですか?

1)再帰関数外

let doSomething n = ...
let rec doSomethingElse x =
    match x with
    | yourDone -> ...
    | yourNotDone -> doSomethingElse (doSomething x)

2)再帰関数の内部

let rec doSomethingElse x =
    let doSomething n = ...
    match x with
    | yourDone -> ...
    | yourNotDone -> doSomethingElse (doSomething x)

3)第3の関数の内部に両方をカプセル化する

let doSomethingElse x =
    let doSomething n = ...
    let innerDoSomethingElse =
        match x with
        | yourDone -> ...
        | yourNotDone -> innerDoSomethingElse (doSomething x)

4)もっと良いものがありますか?

6
なぜ近くの投票?これは非常に良い/妥当な質問のようです。
追加された 著者 Daniel,

1 答え

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> add = new [email protected]();
        return FSharpFunc.InvokeFast(add, x, 1);
    }

    public static int f2(int x) {
        FSharpFunc add = new [email protected](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 [email protected] : OptimizedClosures.FSharpFunc {
        internal [email protected]() { }

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

    [Serializable]
    internal class [email protected] : FSharpFunc {
        public int x;

        internal [email protected](int x) {
            this.x = x;
        }

        public override int Invoke(int a) {
            return (a + this.x);
        }
    }
}

内部関数の唯一の追加コストは、 FSharpFunc のインスタンスを新しくすることです - これはごくわずかです。

非常にパフォーマンスが重視されない限り、私は最も理にかなったスコープ、つまり可能な限り狭いスコープを使用します。

5
追加された
最後の文を参照してください。私はそれをベンチマークする時間がありませんが、私は唯一の顕著な違いを述べました。
追加された 著者 Daniel,
答えはあなたのスニペットから推測できるかもしれませんが、本当にそれを綴るべきです。
追加された 著者 Ramon Snir,
FSharpFunc を作成すると、大量のコードを使用するとパフォーマンスが低下する可能性がありますが、ほとんどの場合、問題はありません。
追加された 著者 Ramon Snir,