2011-01-02 42 views
7

Nếu bạn xác định phương thức While của đối tượng trình tạo, bạn có thể sử dụng while vòng trong computation expressions của mình. Chữ ký của phương pháp While là:Vai trò của `while`-loop trong biểu thức tính toán trong F # là gì?

member b.While (predicate:unit->bool, body:M<'a>) : M<'a> 

Để so sánh, chữ ký của phương pháp For là:

member b.For (items:seq<'a>, body:unit->M<'a>) : M<'a> 

Bạn nên lưu ý rằng, trong While -method, cơ thể là một loại đơn giản và không phải chức năng như trong phương thức For.

Bạn có thể nhúng một số câu lệnh khác, như let và các cuộc gọi chức năng bên trong biểu thức tính toán của bạn, nhưng chúng có thể thực thi không thể thực hiện trong một while - nhiều lần.

builder { 
    while foo() do 
     printfn "step" 
     yield bar() 
} 

Tại sao while - vòng lặp không được thực hiện nhiều lần, nhưng chỉ lặp lại? Tại sao sự khác biệt đáng kể từ các vòng lặp? Tốt hơn, có một số chiến lược dự định sử dụng các vòng lặp trong tính toán biểu thức?

Trả lời

3

Nếu bạn nhìn vào how computation expressions are evaluated, bạn sẽ thấy rằng

while foo() do 
    printfn "step" 
    yield bar() 

được phiên dịch sang một cái gì đó giống như

builder.While(fun() -> foo(), 
       builder.Delay(fun() -> 
           printfn "step" 
           builder.Yield(bar())))) 

dịch này cho phép cơ thể của vòng lặp while để được đánh giá nhiều lần. Mặc dù chữ ký loại của bạn là chính xác cho một số biểu thức tính toán (chẳng hạn như seq hoặc async), lưu ý rằng việc chèn cuộc gọi đến Delay có thể dẫn đến chữ ký khác. Ví dụ, bạn có thể định nghĩa một người thợ xây danh sách như thế này:

type ListBuilder() = 
    member x.Delay f = f 
    member x.While(f, l) = if f() then l() @ (x.While(f, l)) else [] 
    member x.Yield(i) = [i] 
    member x.Combine(l1,l2) = l1 @ l2() 
    member x.Zero() = [] 
    member x.Run f = f() 

let list = ListBuilder() 

Bây giờ bạn có thể đánh giá một biểu thức như:

list { 
    let x = ref 0 
    while !x < 10 do 
    yield !x 
    x := !x + 1 
} 

để có được tương đương với [0 .. 9].

Ở đây, phương pháp While của chúng tôi có chữ ký (unit -> bool) * (unit -> 'a list) -> 'a list, thay vì (unit -> bool) * 'a list -> 'a list. Nói chung, khi hoạt động Delay có loại (unit -> M<'a>) -> D<M<'a>>, chữ ký của phương thức While sẽ là (unit -> bool) * D<M<'a>> -> M<'a>.

+0

Tốt. Tôi không biết về 'Chạy'. –

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