2011-01-02 21 views
7

यदि आप बिल्डर-ऑब्जेक्ट की While विधि को परिभाषित करते हैं, तो आप अपने computation expressions में while -loops का उपयोग कर सकते हैं। While विधि के हस्ताक्षर है:एफ # में गणना अभिव्यक्तियों में `while`-loops की भूमिका क्या है?

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

तुलना के लिए, For विधि के हस्ताक्षर है:

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

आपको लगता है कि नोटिस देना चाहिए, While -method में, शरीर एक सरल प्रकार है , और For विधि में कोई फ़ंक्शन नहीं है।

आप let जैसे कुछ अन्य बयान, और अपने अभिकलन-भाव के अंदर समारोह कॉल एम्बेड कर सकते हैं, लेकिन उन असंभव एक while -loop एक बार से अधिक में निष्पादित कर सकते हैं।

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

क्यों while एक बार से अधिक मार डाला जाता है -loop नहीं, लेकिन केवल दोहराया? फॉर-लूप से महत्वपूर्ण अंतर क्यों? बेहतर अभी तक, गणना-अभिव्यक्तियों में जबकि-loops का उपयोग करने के लिए कुछ इरादा रणनीति है?

उत्तर

3

आप how computation expressions are evaluated को देखें, तो आपको लगता है कि

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

तरह

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

कुछ करने के लिए अनुवाद किया है यह अनुवाद जबकि पाश के शरीर को कई बार मूल्यांकन किया जाना करने की अनुमति देता देखेंगे। जबकि आपके प्रकार के हस्ताक्षर कुछ गणना अभिव्यक्तियों (जैसे seq या async) के लिए सटीक हैं, ध्यान दें कि Delay पर कॉल का सम्मिलन परिणामस्वरूप एक अलग हस्ताक्षर हो सकता है। उदाहरण के लिए, आप इस प्रकार की सूची बिल्डर निर्धारित कर सकते हैं: [0 .. 9] के बराबर लाने के लिए

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

:

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() 

अब आप की तरह एक अभिव्यक्ति का मूल्यांकन कर सकते हैं।

यहां, हमारे While विधि में के बजाय हस्ताक्षर (unit -> bool) * (unit -> 'a list) -> 'a list है। आम तौर पर, जब Delay ऑपरेशन में (unit -> M<'a>) -> D<M<'a>> टाइप किया गया है, While विधि का हस्ताक्षर (unit -> bool) * D<M<'a>> -> M<'a> होगा।

+0

अच्छा। मुझे 'रन' के बारे में पता नहीं था। –