F # cinsinden dışarıda bir özyinelemeli fonksiyon içinde tanımlayıcı fonksiyonların performans yan etkileri nelerdir

Başka bir işleve dayanan bir özyineleme işleviniz varsa, bunu uygulamak için tercih edilen yol nedir?

1) özyinelemeli işlev dışında

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

2) özyinelemeli fonksiyonun içinde

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

3) üçüncü bir fonksiyonun her ikisini de içine alır

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

4) daha iyi bir şey?

6
Neden yakın oylama? Bu çok iyi/makul bir soru gibi görünüyor.
katma yazar Daniel, kaynak

1 cevap

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

Çevirir:

[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);
        }
    }
}

Bir iç işlev için tek ek maliyet, FSharpFunc örneğinin yeniden güncellenmesidir - göz ardı edilebilir gibi görünüyor.

Çok performansa duyarlı değilseniz, en mantıklı olan, yani mümkün olan en dar kapsamı seçerim.

5
katma
Son cümleyi gör. Karşılaştırmak için zamanım yok, ama fark edilen tek farktan bahsettim.
katma yazar Daniel, kaynak
Yanıt, snippet'larınızdan kötüye kullanılabilir, ancak gerçekten hecelemeniz gerekir.
katma yazar Ramon Snir, kaynak
FSharpFunc oluşturmak, ağır kod kullanımı için performansa zarar verebilir, ancak çoğu durumda bunun önemi yoktur.
katma yazar Ramon Snir, kaynak