2011-10-27 17 views
6

Nếu bạn có hàm đệ quy dựa trên một số hàm khác thì cách ưa thích để thực hiện điều đó là gì?Hiệu ứng phụ hiệu quả của việc xác định hàm bên trong hàm đệ quy so với bên ngoài trong F #

1) bên ngoài hàm đệ quy

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

2) bên trong hàm đệ quy

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

3) đóng gói cả hai bên trong một hàm thứ ba

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

4) một cái gì đó thậm chí tốt hơn?

+3

Tại sao bỏ phiếu đóng? Điều này có vẻ như một câu hỏi rất tốt/hợp lý. – Daniel

Trả lời

5
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 

Chuyển thành:

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

    public static int f(int x) { 
     FSharpFunc<int, FSharpFunc<int, int>> add = new [email protected](); 
     return FSharpFunc<int, int>.InvokeFast<int>(add, x, 1); 
    } 

    public static int f2(int x) { 
     FSharpFunc<int, int> 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<int, int, int> { 
     internal [email protected]() { } 

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

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

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

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

Các chi phí bổ sung duy nhất cho một chức năng bên trong được new'ing lên một thể hiện của FSharpFunc --seems không đáng kể.

Trừ khi bạn đang rất hiệu suất nhạy cảm, tôi sẽ đi với phạm vi có ý nghĩa nhất, đó là phạm vi hẹp nhất có thể.

+0

Câu trả lời có thể là không thể tránh khỏi các đoạn trích của bạn, nhưng bạn thực sự nên đánh vần nó. –

+0

Xem câu cuối cùng. Tôi không có thời gian để đánh giá nó, nhưng tôi đã đề cập đến sự khác biệt đáng chú ý duy nhất. – Daniel

+0

Tạo một 'FSharpFunc' có thể làm hỏng hiệu suất cho việc sử dụng mã nặng, nhưng đối với hầu hết các trường hợp, nó sẽ không thành vấn đề. –

Các vấn đề liên quan