जवाबों:
का उपयोग करना Maybe
(या उसके चचेरे भाई Either
जो मूल रूप से उसी तरह काम करता है लेकिन आपको इसके स्थान पर एक मनमाना मूल्य वापस करने की अनुमति देता है Nothing
) अपवादों से थोड़ा अलग उद्देश्य प्रदान करता है। जावा के संदर्भ में, यह रनटाइम अपवाद के बजाय एक जाँच अपवाद है। यह किसी ऐसी चीज का प्रतिनिधित्व करता है, जिसकी अपेक्षा आपको एक ऐसी त्रुटि से करनी है, जिसकी अपेक्षा आपने नहीं की थी।
तो एक फ़ंक्शन जैसा indexOf
कोई Maybe
मान लौटाएगा क्योंकि आप इस संभावना की अपेक्षा करते हैं कि आइटम सूची में नहीं है। यह null
एक प्रकार्य-सुरक्षित तरीके को छोड़कर किसी फ़ंक्शन से लौटने जैसा है, जो आपको null
मामले से निपटने के लिए मजबूर करता है। Either
उसी तरह से काम करता है, सिवाय इसके कि आप त्रुटि मामले से जुड़ी जानकारी वापस कर सकते हैं, इसलिए यह वास्तव में अपवाद के समान है Maybe
।
तो Maybe
/ Either
दृष्टिकोण के फायदे क्या हैं ? एक के लिए, यह भाषा का प्रथम श्रेणी का नागरिक है। चलो Either
एक अपवाद का उपयोग करके फ़ंक्शन की तुलना करें । अपवाद मामले के लिए, आपका एकमात्र वास्तविक सहारा एक try...catch
बयान है। के लिए Either
समारोह, आप मौजूदा combinators का उपयोग प्रवाह नियंत्रण स्पष्ट करने के सकता है। यहां कुछ उदाहरण दिए गए हैं:
सबसे पहले, मान लें कि आप कई कार्यों को आज़माना चाहते हैं जो एक पंक्ति में त्रुटि कर सकते हैं जब तक कि आपको एक ऐसा नहीं मिलता। यदि आपको कोई त्रुटि नहीं मिलती है, तो आप एक विशेष त्रुटि संदेश वापस करना चाहते हैं। यह वास्तव में एक बहुत ही उपयोगी पैटर्न है लेकिन इसका उपयोग करते हुए एक भयानक दर्द होगा try...catch
। खुशी से, चूंकि Either
सिर्फ एक सामान्य मूल्य है, आप कोड को अधिक स्पष्ट करने के लिए मौजूदा कार्यों का उपयोग कर सकते हैं:
firstThing <|> secondThing <|> throwError (SomeError "error message")
एक अन्य उदाहरण में एक वैकल्पिक कार्य है। मान लें कि आपके पास चलाने के लिए कई कार्य हैं, जिसमें एक क्वेरी को अनुकूलित करने का प्रयास करना शामिल है। यदि यह विफल रहता है, तो आप किसी भी तरह से सब कुछ चलाना चाहते हैं। आप कोड कुछ लिख सकते हैं जैसे:
do a <- getA
b <- getB
optional (optimize query)
execute query a b
ये दोनों मामले स्पष्ट और उपयोग करने से कम हैं try..catch
, और, अधिक महत्वपूर्ण बात, अधिक अर्थपूर्ण। किसी फ़ंक्शन का उपयोग करना <|>
या हमेशा अपवादों को हैंडल करने की तुलना में optional
अपने इरादों को अधिक स्पष्ट try...catch
करना।
यह भी ध्यान दें कि आपको अपने कोड को लाइनों की तरह नहीं रखना है if a == Nothing then Nothing else ...
! इलाज Maybe
और Either
एक सनक के रूप में इस से बचने के लिए पूरे बिंदु है । आप बाइंड फ़ंक्शन में प्रचार शब्दार्थ को सांकेतिक शब्दों में बदलना कर सकते हैं ताकि आपको मुफ्त में अशक्त / त्रुटि जांच मिल सके। आपके पास स्पष्ट रूप से जांचने का एकमात्र समय है यदि आप Nothing
दिए गए ए के अलावा कुछ और वापस करना चाहते हैं Nothing
, और फिर भी यह आसान है: उस कोड को अच्छे बनाने के लिए मानक पुस्तकालय कार्यों का एक समूह है।
अंत में, एक और लाभ यह है कि एक Maybe
/ Either
प्रकार सिर्फ सरल है। अतिरिक्त कीवर्ड या नियंत्रण संरचनाओं के साथ भाषा का विस्तार करने की आवश्यकता नहीं है - सब कुछ सिर्फ एक पुस्तकालय है। चूंकि वे सामान्य मान हैं, इसलिए यह टाइप सिस्टम को सरल बनाता है - जावा में, आपको टाइप (जैसे रिटर्न प्रकार) और प्रभाव (जैसे throws
स्टेटमेंट) में अंतर करना होगा, जहां आप उपयोग नहीं करेंगे Maybe
। वे भी किसी अन्य उपयोगकर्ता-परिभाषित प्रकार की तरह व्यवहार करते हैं - भाषा में बेक किए गए विशेष त्रुटि-हैंडलिंग कोड की आवश्यकता नहीं है।
एक अन्य जीत यह है कि Maybe
/ Either
फंक्शनलर्स और मोनड्स हैं, जिसका अर्थ है कि वे मौजूदा मोनाड नियंत्रण प्रवाह कार्यों का लाभ उठा सकते हैं (जिनमें से एक उचित संख्या है) और, सामान्य रूप से, अन्य साधुओं के साथ अच्छी तरह से खेलते हैं।
उस ने कहा, कुछ कैवियट हैं। एक के लिए, न तो Maybe
और न ही अनियंत्रित अपवादों को Either
प्रतिस्थापित करें । आप 0 से विभाजित करने जैसी चीजों को संभालने के लिए कुछ और तरीका चाहते हैं क्योंकि यह एक दर्द होगा कि हर एक डिवीजन का मूल्य वापस आ जाए ।Maybe
एक अन्य समस्या में कई प्रकार की त्रुटियां हैं (यह केवल लागू होती है Either
)। अपवादों के साथ, आप किसी भी भिन्न प्रकार के अपवादों को एक ही फ़ंक्शन में फेंक सकते हैं। के साथ Either
, आपको केवल एक प्रकार मिलता है। इसे सब-टाइपिंग या ADT से जोड़ा जा सकता है जिसमें सभी विभिन्न प्रकार की त्रुटियां हैं, जैसे कि कंस्ट्रक्टर (यह दूसरा दृष्टिकोण है जो आमतौर पर हास्केल में उपयोग किया जाता है)।
फिर भी, मैं अधिक Maybe
/ Either
दृष्टिकोण को पसंद करता हूं क्योंकि मुझे यह सरल और अधिक लचीला लगता है।
OpenFile()
फेंक FileNotFound
या NoPermission
या सकता है TooManyDescriptors
। कोई भी इस जानकारी को नहीं ले जाता है।if None return None
-स्टाइल स्टेटमेंट के।सबसे महत्वपूर्ण बात, एक अपवाद और शायद एक सनक के अलग-अलग उद्देश्य हैं - एक अपवाद का उपयोग किसी समस्या को इंगित करने के लिए किया जाता है, जबकि एक शायद नहीं है।
"नर्स, अगर कमरा 5 में कोई मरीज है, तो क्या आप उसे इंतजार करने के लिए कह सकते हैं?"
("अगर" नोटिस - इसका मतलब है कि डॉक्टर शायद एक सनक की उम्मीद कर रहे हैं )
None
मानों को केवल प्रचारित किया जा सकता है)। आपकी बात 5 ही सही है ... सवाल यह है कि कौन सी परिस्थितियाँ स्पष्ट रूप से असाधारण हैं? जैसा कि यह पता चला है ... कई नहीं ।
bind
इस तरह से लिख सकते हैं कि परीक्षण के लिए None
एक सिंटैक्टिक ओवरहेड को लाइक नहीं करता है। एक बहुत ही सरल उदाहरण, C # बस Nullable
ऑपरेटरों को उचित रूप से अधिभारित करता है। None
प्रकार का उपयोग करते समय भी आवश्यक के लिए कोई जाँच नहीं । बेशक चेक अभी भी किया जाता है (यह सुरक्षित है), लेकिन पर्दे के पीछे और अपने कोड को अव्यवस्थित नहीं करता है। वही कुछ आपत्ति के लिए मेरी आपत्ति (5) पर लागू होता है, लेकिन मैं मानता हूं कि यह हमेशा लागू नहीं हो सकता है।
Maybe
प्रचार प्रसार करना None
है। इसका मतलब है कि यदि आप None
दिए गए रिटर्न को वापस करना चाहते हैं None
, तो आपको कोई विशेष कोड लिखने की आवश्यकता नहीं है। आपको मैच के लिए केवल तभी समय चाहिए जब आप कुछ विशेष करना चाहते हैं None
। आपको कभी भी if None then None
कथनों की आवश्यकता नहीं है ।
null
बिल्कुल वैसे ही चेक करें (जैसे if Nothing then Nothing
) मुफ्त में क्योंकि Maybe
एक सन्यासी है। यह बाइंड की परिभाषा में एन्कोडेड है ( >>=
) के लिए Maybe
।
Either
) ले जा सकता है जो बिल्कुल व्यवहार करता है Maybe
। Maybe
वास्तव में सिर्फ एक विशेष मामला है क्योंकि दोनों के बीच स्विच करना वास्तव में सरल है Either
। (में हास्केल, तो आप के बारे में सोच सकता है Maybe
के रूप में Either ()
।)
"शायद" मैं अपवादों के लिए एक प्रतिस्थापन नहीं हूं। अपवाद का उपयोग असाधारण मामलों में किया जाता है (उदाहरण के लिए: db कनेक्शन खोलना और db सर्वर वहां नहीं है, हालांकि यह होना चाहिए)। "शायद" मैं ऐसी स्थिति के लिए मॉडलिंग कर रहा हूं जब आपके पास वैध मूल्य हो सकता है या नहीं; कहते हैं कि आपको एक कुंजी के लिए एक शब्दकोश से एक मूल्य मिल रहा है: यह हो सकता है या नहीं हो सकता है - इनमें से किसी भी परिणाम के बारे में "असाधारण" कुछ भी नहीं है।
मैं दूसरे टिखोन का जवाब देता हूं, लेकिन मुझे लगता है कि बहुत महत्वपूर्ण व्यावहारिक बिंदु है जो हर किसी को याद आ रहा है:
Either
तंत्र को धागों से जोड़ा नहीं जाता है।तो कुछ जो हम आजकल वास्तविक जीवन में देख रहे हैं, वह यह है कि कई अतुल्यकालिक प्रोग्रामिंग समाधान Either
त्रुटि हैंडलिंग के -स्टाइल के एक संस्करण को अपना रहे हैं । जावास्क्रिप्ट वादों पर विचार करें , जैसा कि इनमें से किसी भी लिंक में विस्तृत है:
वादों की अवधारणा आपको इस तरह अतुल्यकालिक कोड लिखने की अनुमति देती है (अंतिम लिंक से लिया गया):
var greetingPromise = sayHello();
greetingPromise
.then(addExclamation)
.then(function (greeting) {
console.log(greeting); // 'hello world!!!!’
}, function(error) {
console.error('uh oh: ', error); // 'uh oh: something bad happened’
});
मूल रूप से, एक वादा एक वस्तु है कि:
मूल रूप से, के बाद से भाषा की मूल अपवाद समर्थन काम जब अपने गणना एक से अधिक थ्रेड भर में हो रहा है नहीं है, एक वादे कार्यान्वयन एक त्रुटि हैंडलिंग प्रणाली प्रदान करने के लिए है, और इन हास्केल के समान monads होने के लिए बाहर बारी Maybe
/ Either
प्रकार के।
हास्केल प्रकार प्रणाली को उपयोगकर्ता की संभावना को स्वीकार करने की आवश्यकता होगी Nothing
, जबकि प्रोग्रामिंग भाषाओं को अक्सर आवश्यकता नहीं होती है कि अपवाद पकड़ा जाए। इसका मतलब है कि हम संकलन-समय पर यह जान लेंगे कि उपयोगकर्ता ने किसी त्रुटि के लिए जाँच की है।
throws NPE
हर एक हस्ताक्षर और catch(...) {throw ...}
हर एक विधि निकाय में जोड़ना पड़ेगा । लेकिन मेरा मानना है कि शायद एक ही अर्थ में जाँच के लिए बाजार है: शायद अशक्तता वैकल्पिक है और प्रकार प्रणाली में ट्रैक किया गया है।
हो सकता है कि मोनाड मूल रूप से मुख्य मुख्यधारा की भाषा के "नल का अर्थ त्रुटि" की जाँच के उपयोग के समान हो (सिवाय इसके कि अशक्त की जाँच की आवश्यकता है), और बड़े पैमाने पर समान फायदे और नुकसान हैं।
Maybe
नंबर जोड़ सकते हैं , और परिणाम एक बार फिर से वैकल्पिक मूल्य है। a + b
None
Maybe
प्रकार है, लेकिन का उपयोग कर Maybe
एक इकाई के रूप में वाक्य रचना चीनी कि व्यक्त की अनुमति देता है एक बहुत अधिक सुंदर ढंग से अशक्त-ish तर्क कहते हैं।
फैक्टिंग हैंडलिंग और टेस्टिंग के लिए एक्सेप्शन हैंडलिंग एक वास्तविक दर्द हो सकता है। मुझे पता है कि अजगर "सिंटैक्स" के साथ अच्छा प्रदान करता है जो आपको कठोर "कोशिश ... पकड़" ब्लॉक के बिना अपवादों को फंसाने की अनुमति देता है। लेकिन जावा में, उदाहरण के लिए, पकड़ने की कोशिश करें ब्लॉक बड़े हैं, बॉयलरप्लेट, या तो वर्बोज़ या अत्यंत क्रिया, और कठिन ब्रेक अप करने के लिए। उसके ऊपर, जावा ने सभी शोरों को चेक किए गए बनाम अनियंत्रित अपवादों के चारों ओर जोड़ा।
अगर, इसके बजाय, आपका मोनाड अपवादों को पकड़ता है और उन्हें मोनैडिक स्पेस की संपत्ति के रूप में मानता है (कुछ प्रसंस्करण विसंगतियों के बजाय), तो आप मिक्स करने के लिए स्वतंत्र हैं और फ़ंक्शन को उस स्पेस में बाँध देते हैं, जो वे फेंकते हैं या पकड़ते हैं।
यदि, बेहतर, अभी तक, आपका मोनाड उन स्थितियों को रोकता है, जहां अपवाद हो सकते हैं (जैसे कि संभवत: एक अशक्त जांच को धक्का देना), तो और भी बेहतर। अगर ... तो बहुत है, बहुत आसान कारक और परीक्षण की तुलना में कोशिश ... पकड़।
मैंने जो देखा है, उसमें से प्रत्येक फ़ंक्शन के रिटर्न (उत्तर, त्रुटि) को निर्दिष्ट करके एक समान दृष्टिकोण ले रहा है। यह फ़ंक्शन को एक मोनाड स्पेस में "उठाने" के समान है, जहां कोर उत्तर प्रकार एक त्रुटि संकेत के साथ सजाया गया है, और प्रभावी ढंग से साइड-स्टेपिंग थ्रोइंग और अपवादों को पकड़ रहा है।