रीड पहले से ही समझाया गया है कि क्यों .NET अपवाद OCaml अपवादों से अलग व्यवहार करते हैं। सामान्यतः, .NET अपवाद केवल असाधारण परिस्थितियों के लिए उपयुक्त हैं और उस उद्देश्य के लिए डिज़ाइन किए गए हैं। ओकैमल में अधिक हल्के मॉडल हैं और इसलिए इन्हें कुछ नियंत्रण प्रवाह पैटर्न को लागू करने के लिए भी उपयोग किया जाता है।
ओकैमल में एक ठोस उदाहरण देने के लिए आप लूप को तोड़ने के लिए अपवाद का उपयोग कर सकते हैं। उदाहरण के लिए, कहें कि आपके पास test
फ़ंक्शन है जो परीक्षण करता है कि कोई संख्या एक संख्या है जिसे हम चाहते हैं। 1 से 100 तक नंबर और रिटर्न पहले नंबर से मेल खाते पर निम्नलिखित दोहराता:
// Simple exception used to return the result
exception Returned of int
try
// Iterate over numbers and throw if we find matching number
for n in 0 .. 100 do
printfn "Testing: %d" n
if test n then raise (Returned n)
-1 // Return -1 if not found
with Returned r -> r // Return the result here
अपवाद के बिना इसे लागू करने के लिए, आप दो विकल्प हैं। आप एक पुनरावर्ती समारोह समान व्यवहार है कि लिख सकता है - अगर आप find 0
फोन (और यह सी # में return n
for
अंदर पाश का उपयोग कर के रूप में मूलतः एक ही आईएल कोड को संकलित किया गया है):
let rec find n =
printfn "Testing: %d" n
if n > 100 then -1 // Return -1 if not found
elif test n then n // Return the first found result
else find (n + 1) // Continue iterating
एन्कोडिंग पुनरावर्ती कार्यों का उपयोग कर सकते हैं थोड़ा लंबा हो, लेकिन आप एफ # लाइब्रेरी द्वारा प्रदान किए गए मानक कार्यों का भी उपयोग कर सकते हैं। कोड को फिर से लिखने का यह सबसे अच्छा तरीका है जो नियंत्रण प्रवाह के लिए ओकैमल अपवादों का उपयोग करेगा। इस मामले में, आप लिख सकते हैं:
// Find the first value matching the 'test' predicate
let res = seq { 0 .. 100 } |> Seq.tryFind test
// This returns an option type which is 'None' if the value
// was not found and 'Some(x)' if the value was found.
// You can use pattern matching to return '-1' in the default case:
match res with
| None -> -1
| Some n -> n
यदि आप विकल्प प्रकार से परिचित नहीं हैं, तो कुछ प्रारंभिक सामग्री देखें। F# wikibook has a good tutorial और MSDN documentation has useful examples भी।
Seq
मॉड्यूल से उपयुक्त फ़ंक्शन का उपयोग अक्सर कोड को बहुत छोटा बनाता है, इसलिए यह प्राथमिक है। यह सीधे रिकर्सन का उपयोग करने से थोड़ा कम कुशल हो सकता है, लेकिन ज्यादातर मामलों में, आपको इसके बारे में चिंता करने की आवश्यकता नहीं है।
संपादित करें: मैं वास्तविक प्रदर्शन के बारे में उत्सुक था। Seq.tryFind
का उपयोग करने वाला संस्करण अधिक कुशल है यदि इनपुट (सूची आवंटन की लागत के कारण) के बजाय आलसी उत्पन्न अनुक्रम seq { 1 .. 100 }
है। इन परिवर्तनों, और test
समारोह है कि 25 वीं तत्व देता है, समय मेरी मशीन पर कोड 100000 बार चलाने के लिए आवश्यक के साथ है:
exceptions 2.400sec
recursion 0.013sec
Seq.tryFind 0.240sec
यह बहुत तुच्छ नमूना है, इसलिए मैं समाधान का उपयोग कर Seq
आम तौर पर नहीं चलेंगे लगता है रिकर्सन का उपयोग करके लिखे समकक्ष कोड की तुलना में 10 गुना धीमा। मंदी शायद अतिरिक्त डेटा संरचनाओं (अनुक्रम, बंद करने, ... का प्रतिनिधित्व करने वाली वस्तु) के आवंटन के कारण है और अतिरिक्त संकेत के कारण भी (कोड को केवल सादा संख्यात्मक संचालन और कूद के बजाए कई वर्चुअल विधि कॉल की आवश्यकता है)। हालांकि, अपवाद भी अधिक महंगा है और कोड कम या किसी भी तरह से अधिक पठनीय नहीं कर सकता हूँ ...
पिछली [ओकैमल अपवादों की हल्केपन की चर्चा] [http://stackoverflow.com/questions/8564025/ocaml-internals-exceptions) –
@ जेफरीस्कोफिल्ड धन्यवाद, हालांकि मैं सीएलआर से संबंधित पहलुओं में अधिक रुचि रखता हूं । – gliderkite