पहली बार मैं/तोड़ने के लिए तक पहुँचने के लिए OCaml/एफ # जारी रखने के लिए चला गया, यह मुझे एक के लिए फेंक दिया (अनंत (fshub पर this post से संपादित)) लूप, तो बोलने के लिए, क्योंकि ऐसी कोई चीज मौजूद नहीं है! ओकैमल में, कोई लूप से तोड़ने के लिए अपवादों का उपयोग कर सकता है क्योंकि वे बहुत सस्ते हैं, लेकिन F # (में।नेट) ओवरहेड काफी सामान्य है और "सामान्य" प्रवाह नियंत्रण के लिए उपयोगी नहीं है।
यह थोड़ी देर पहले (कुछ समय मारने के लिए) सॉर्ट एल्गोरिदम के साथ खेलते समय आया, जो दोहराने/तब तक टूटने का भारी उपयोग करता है। यह मुझे मारा कि रिकर्सिव पूंछ कॉल फ़ंक्शन एक ही परिणाम प्राप्त कर सकते हैं, केवल पठनीयता के लिए थोड़ी सी डिंग के साथ। इसलिए, मैंने 'म्यूटेबल बीडोन' और 'बीडीओएन नहीं' को फेंक दिया और इन अनिवार्य संरचनाओं के बिना कोड लिखने की कोशिश की। निम्नलिखित लूपिंग भागों को दूर करता है और दिखाता है कि दोहराना/कब तक, लिखना/कब, करना/करना, ब्रेक/जारी रखना, और टेलीक-इन-द-मिडिल स्टाइल कोड टेलकॉल का उपयोग करके लिखना है। ये सभी परंपरागत एफ # 'जबकि' कथन के समान गति से चलने लगते हैं, लेकिन आपका माइलेज भिन्न हो सकता है (कुछ प्लेटफॉर्म ठीक से टेलिकॉल को लागू नहीं कर सकते हैं और इसलिए जब तक वे पैच नहीं किए जाते हैं तो गलती हो सकती है)। अंत में तुलना के लिए, दोनों शैलियों में लिखे गए एक (खराब) सॉर्ट एल्गोरिदम है।
चलो परंपरागत एफ # अनिवार्य शैली में लिखे गए 'डू/एंड' लूप के साथ शुरू करते हैं, फिर कार्यात्मक विविधताएं देखें जो समान प्रकार के लूप दोनों के साथ-साथ विभिन्न अर्थशास्त्र जैसे/करते हैं, दोहराना/जब तक, बीच में परीक्षण करें, और यहां तक कि तोड़ें/जारी रखें (मोनैड के बिना .. उम, वर्कफ़्लोज़!)।
#light
(* something to work on... *)
let v = ref 0
let f() = incr v;
let g() = !v;
let N = 100000000
let imperDoWhile() =
let mutable x = 0
let mutable bDone = false
while not bDone do
f()
x <- x + 1
if x >= N then bDone <- true
ठीक है, यह काफी आसान है। ध्यान रखें कि एफ() को कम से कम एक बार (कब/करते समय) कहा जाता है।
यहां एक ही कोड है, लेकिन एक कार्यात्मक शैली में। ध्यान दें कि हमें यहां एक म्यूटेबल घोषित करने की आवश्यकता नहीं है।
let funDoWhile() =
let rec loop x =
f() (*Do*)
if x < N then (*While*)
loop (x+1)
loop 0
हम किसी ब्लॉक के अंदर फ़ंक्शन कॉल डालकर परंपरागत/समय के दौरान इसे स्पिन कर सकते हैं।
let funWhileDo() =
let rec loop x =
if x < N then (*While*)
f() (*Do*)
loop (x+1)
loop 0
कुछ स्थिति सत्य होने तक ब्लॉक को दोहराने के बारे में (दोहराना/कब तक)? काफी आसान ...
let funRepeatUntil() =
let rec loop x =
f() (*Repeat*)
if x >= N then() (*Until*)
else loop (x+1)
loop 0
मोनाड-कम ब्रेक के बारे में क्या था? खैर, बस एक सशर्त अभिव्यक्ति प्रस्तुत करें जो 'यूनिट' लौटाती है, जैसे:
let funBreak() =
let rec loop() =
let x = g()
if x > N then() (*break*)
else
f()
loop()
loop()
जारी रखने के बारे में कैसे? खैर, यह सिर्फ लूप के लिए एक और कॉल है! सबसे पहले, एक वाक्य रचना बैसाखी के साथ:
let funBreakContinue() =
let break'() =()
let rec continue'() =
let x = g()
if x > N then break'()
elif x % 2 = 0 then
f(); f(); f();
continue'()
else
f()
continue'()
continue'()
और फिर फिर से (बदसूरत) वाक्य रचना बैसाखी के बिना:
let funBreakContinue'() =
let rec loop() =
let x = g()
if x > N then()
elif x % 2 = 0 then
f(); f(); f();
loop()
else
f()
loop()
loop()
आसान पाई के रूप में!
इन लूप रूपों का एक अच्छा परिणाम यह है कि यह आपके लूप में राज्यों को स्पॉट और कार्यान्वित करना आसान बनाता है। उदाहरण के लिए, एक बुलबुला सॉर्ट लगातार एक संपूर्ण सरणी पर लूप करता है, जो मूल्यों से बाहर हो जाता है, जैसा कि उन्हें पाता है। यह ट्रैक करता है कि सरणी पर एक पास किसी एक्सचेंज का उत्पादन करता है या नहीं। यदि नहीं, तो प्रत्येक मान सही जगह पर होना चाहिए, इसलिए क्रम समाप्त हो सकता है। एक अनुकूलन के रूप में, सरणी के माध्यम से प्रत्येक पास पर, सरणी में अंतिम मान सही स्थान पर क्रमबद्ध होता है। तो, लूप को हर बार एक से छोटा किया जा सकता है। अधिकांश एल्गोरिदम एक स्वैप की जांच करते हैं और हर बार एक "bmodified" ध्वज अपडेट करते हैं। हालांकि, एक बार पहला स्वैप पूरा हो जाने के बाद, उस असाइनमेंट की कोई आवश्यकता नहीं है; यह पहले से ही सच है!
यहां एफ # कोड है जो एक बबल सॉर्ट लागू करता है (हाँ, बबल सॉर्ट भयानक एल्गोरिदम है; क्विकसॉर्ट चट्टानों)। अंत में एक अनिवार्य कार्यान्वयन है जो राज्य को नहीं बदलता है; यह प्रत्येक एक्सचेंज के लिए bmodified ध्वज अद्यतन करता है।दिलचस्प बात यह है कि अनिवार्य समाधान छोटे सरणी पर तेज़ है और बड़े पैमाने पर केवल एक प्रतिशत या दो धीमी है। (हालांकि, एक अच्छा उदाहरण के लिए बनाया गया)।
let inline sort2 f i j (a:'a array) =
let i' = a.[ i ]
let j' = a.[ j ]
if f i' j' > 0 then
a.[ i ] <- j'
a.[ j ] <- i'
let bubble f (xs:'a array) =
if xs.Length = 0
then()
let rec modified i endix =
if i = endix then
unmodified 0 (endix-1)
else
let j = i+1
sort2 f i j xs
modified j endix
and unmodified i endix =
if i = endix then
()
else
let j = i+1
let i' = xs.[ i ]
let j' = xs.[ j ]
if f i' j' > 0 then
xs.[ i ] <- j'
xs.[ j ] <- i'
modified j endix
else
unmodified j endix
in unmodified 0 (xs.Length-1)
let bubble_imperitive f (xs:'a array) =
let mutable bModified = true
let mutable endix = xs.Length - 1
while bModified do
bModified <- false
endix <- endix - 1
for i in 0..endix do
let j = i+1
let i' = xs.[ i ]
let j' = xs.[ j ]
if f i' j' > 0 then
xs.[ i ] <- j'
xs.[ j ] <- i'
bModified <- true
done
done
शायद समुदाय विकी होना चाहिए - कोई "उत्तर" प्रति से नहीं होना चाहिए? – Anthony
@ एंथनी, मुझे उम्मीद है कि एक वेबसाइट है, लेकिन अगर ऐसा नहीं है, तो मैं इसे बनाउंगा। – Unknown
ऐसा लगता है कि आपने इस समुदाय को बहुत जल्द बनाया है - कृपया देखें pleac-ocaml – Thelema