क्यों या तो (जाँच) अपवाद का उपयोग?


17

बहुत समय पहले मैंने जावा के बजाय स्काला का उपयोग शुरू नहीं किया था। मेरे लिए भाषाओं के बीच "रूपांतरण" प्रक्रिया Eitherका हिस्सा (चेक किए गए) के बजाय एस का उपयोग करना सीख रहा था Exception। मैं थोड़ी देर के लिए इस तरह से कोडिंग कर रहा हूं, लेकिन हाल ही में मैंने सोचा कि अगर यह वास्तव में जाने का एक बेहतर तरीका है।

एक प्रमुख लाभ Eitherयह है Exceptionकि बेहतर प्रदर्शन है; एक Exceptionढेर का पता लगाने का निर्माण करने की जरूरत है और फेंक दिया जा रहा है। जहाँ तक मुझे समझ में आता है, हालाँकि, फेंकना Exceptionमाँग का हिस्सा नहीं है, लेकिन स्टैक-ट्रेस का निर्माण करना है।

लेकिन फिर भी, एक हमेशा / इनहेरिट निर्माण कर सकते हैं Exceptionके साथ scala.util.control.NoStackTrace, और इससे भी अधिक, मैं मामलों के बहुत सारे देख जहां एक की बाईं ओर Eitherतथ्य एक में है Exception(प्रदर्शन को बढ़ावा देने forgoing)।

एक अन्य लाभ Eitherसंकलक-सुरक्षा है; Scala संकलक गैर-संभाला Exceptions (Java संकलक के विपरीत) के बारे में शिकायत नहीं करेगा । लेकिन अगर मैं गलत नहीं हूँ, तो यह निर्णय उसी तर्क के साथ लिया जाता है जिस पर इस विषय पर चर्चा की जा रही है, इसलिए ...

वाक्य रचना के संदर्भ में, मुझे लगता है कि Exception-स्टाइल रास्ता साफ है। निम्नलिखित कोड ब्लॉक की जांच करें (दोनों समान कार्यक्षमता प्राप्त करते हैं):

Either अंदाज:

def compute(): Either[String, Int] = {

    val aEither: Either[String, String] = if (someCondition) Right("good") else Left("bad")

    val bEithers: Iterable[Either[String, Int]] = someSeq.map {
        item => if (someCondition(item)) Right(item.toInt) else Left("bad")
    }

    for {
        a <- aEither.right
        bs <- reduce(bEithers).right
        ignore <- validate(bs).right
    } yield compute(a, bs)
}

def reduce[A,B](eithers: Iterable[Either[A,B]]): Either[A, Iterable[B]] = ??? // utility code

def validate(bs: Iterable[Int]): Either[String, Unit] = if (bs.sum > 22) Left("bad") else Right()

def compute(a: String, bs: Iterable[Int]): Int = ???

Exception अंदाज:

@throws(classOf[ComputationException])
def compute(): Int = {

    val a = if (someCondition) "good" else throw new ComputationException("bad")
    val bs = someSeq.map {
        item => if (someCondition(item)) item.toInt else throw new ComputationException("bad")
    }

    if (bs.sum > 22) throw new ComputationException("bad")

    compute(a, bs)
}

def compute(a: String, bs: Iterable[Int]): Int = ???

उत्तरार्द्ध मुझे बहुत साफ दिखता है, और दोनों मामलों में विफलता को संभालने वाला कोड (या तो पैटर्न-मिलान Eitherया try-catch) बहुत स्पष्ट है।

तो मेरा सवाल है - क्यों इस्तेमाल Eitherकिया (जाँच) Exception?

अपडेट करें

उत्तर पढ़ने के बाद, मुझे एहसास हुआ कि मैं अपनी दुविधा के मूल को प्रस्तुत करने में विफल रहा हूँ। मेरी चिंता की कमी के साथ नहीं है try-catch; एक या तो एक के Exceptionसाथ "पकड़" सकता है Try, या catchअपवाद को लपेटने के लिए उपयोग कर सकता है Left

मेरे साथ मुख्य समस्या Either/ Tryआती है जब मैं कोड लिखता हूं जो रास्ते में कई बिंदुओं पर विफल हो सकता है; इन परिदृश्यों में, जब एक विफलता का सामना करना पड़ता है, तो मुझे अपने पूरे कोड में उस विफलता का प्रचार करना पड़ता है, इस प्रकार कोड को और अधिक बोझिल बना दिया जाता है (जैसा कि पूर्वोक्त उदाहरणों में दिखाया गया है)।

वास्तव में कोड Exceptionका उपयोग किए बिना कोड को तोड़ने का एक और तरीका है return(जो वास्तव में स्काला में एक और "वर्जित" है)। Eitherदृष्टिकोण की तुलना में कोड अभी भी स्पष्ट होगा , और Exceptionशैली की तुलना में थोड़ा कम साफ होने के बावजूद , गैर-पकड़े गए Exceptionएस का कोई डर नहीं होगा ।

def compute(): Either[String, Int] = {

  val a = if (someCondition) "good" else return Left("bad")

  val bs: Iterable[Int] = someSeq.map {
    item => if (someCondition(item)) item.toInt else return Left("bad")
  }

  if (bs.sum > 22) return Left("bad")

  val c = computeC(bs).rightOrReturn(return _)

  Right(computeAll(a, bs, c))
}

def computeC(bs: Iterable[Int]): Either[String, Int] = ???

def computeAll(a: String, bs: Iterable[Int], c: Int): Int = ???

implicit class ConvertEither[L, R](either: Either[L, R]) {

  def rightOrReturn(f: (Left[L, R]) => R): R = either match {
    case Right(r) => r
    case Left(l) => f(Left(l))
  }
}

मूल रूप से return Leftजगह throw new Exception, और या तो निहित विधि rightOrReturn, स्टैक अप स्वचालित अपवाद प्रचार के लिए एक पूरक है।



ज्यादातर लेख चर्चा की तरह @RobertHarvey लगता है TryEitherबनाम के हिस्से के बारे में Exceptionकहा गया है कि Eitherएस का उपयोग तब किया जाना चाहिए जब विधि का दूसरा मामला "गैर-असाधारण" हो। सबसे पहले, यह एक बहुत, बहुत अस्पष्ट परिभाषा imho है। दूसरा, क्या यह वास्तव में वाक्यविन्यास दंड के लायक है? मेरा मतलब है, मैं वास्तव में Eitherएस का उपयोग करने में कोई आपत्ति नहीं करता अगर यह सिंटैक्स ओवरहेड के लिए नहीं होते जो वे प्रस्तुत करते हैं।
इल रोथ

Eitherमेरे लिए एक सन्यासी की तरह दिखता है। इसका उपयोग तब करें जब आपको कार्यात्मक संरचना के लाभ की आवश्यकता होती है जो कि भिक्षु प्रदान करते हैं। या, शायद नहीं
रॉबर्ट हार्वे

2
@ रोबर्टहवे: तकनीकी रूप से, Eitherअपने आप में एक सन्यासी नहीं है। प्रक्षेपण या तो बाईं ओर या दाईं ओर करने के लिए एक इकाई है, लेकिन Eitherअपने आप में नहीं है। आप इसे एक मोनाड बना सकते हैं, इसे "बायसिंग" करके या तो बाईं ओर या दाईं ओर कर सकते हैं, हालांकि। हालाँकि, तब आप दोनों पक्षों के एक निश्चित शब्दार्थ प्रदान करते हैं Either। स्काला Eitherमूल रूप से निष्पक्ष था, लेकिन हाल ही में पक्षपाती था, इसलिए कि आजकल, यह वास्तव में एक सनक है, लेकिन "मठ" एक निहित संपत्ति नहीं है Either, बल्कि इसके परिणामस्वरूप पक्षपाती है।
जॉर्ग डब्ल्यू मित्तग

@ JörgWMittag: अच्छा, अच्छा। इसका मतलब है कि आप इसका उपयोग अपनी सभी भलाई के लिए कर सकते हैं, और विशेष रूप से परेशान न हों कि परिणामी कोड "साफ" कैसे है (हालांकि मुझे संदेह है कि कार्यात्मक-शैली निरंतरता कोड वास्तव में अपवाद संस्करण की तुलना में क्लीनर होगा)।
रॉबर्ट हार्वे

जवाबों:


13

यदि आप केवल Eitherएक अनिवार्य try-catchब्लॉक की तरह ही उपयोग करते हैं , तो निश्चित रूप से यह एक ही काम करने के लिए अलग-अलग वाक्यविन्यास जैसा दिखता है। Eithersएक मूल्य हैं । उनकी एक जैसी सीमाएँ नहीं हैं। आप ऐसा कर सकते हैं:

  • अपनी कोशिशों को छोटा और सन्निहित रखने की अपनी आदत को रोकें। "कैच" भाग Eithersको "कोशिश" भाग के ठीक बगल में होने की आवश्यकता नहीं है। यह भी एक आम समारोह में साझा किया जा सकता है। इससे चिंताओं को ठीक से अलग करना काफी आसान हो जाता है।
  • Eithersडेटा संरचनाओं में स्टोर करें । आप उनके माध्यम से लूप कर सकते हैं और त्रुटि संदेशों को समेकित कर सकते हैं, पहले वाले को ढूंढें जो विफल नहीं हुआ, आलसी ने उनका मूल्यांकन किया, या इसी तरह।
  • उन्हें बढ़ाएँ और अनुकूलित करें। कुछ बॉयलरप्लेट पसंद नहीं हैं, जिनके साथ आपको लिखने के लिए मजबूर किया जाता है Eithers? आप अपने विशेष उपयोग के मामलों के साथ काम करना आसान बनाने के लिए सहायक कार्य लिख सकते हैं। ट्राइ-कैच के विपरीत, आप स्थायी रूप से केवल डिफ़ॉल्ट इंटरफ़ेस के साथ नहीं अटकते हैं, जो भाषा डिजाइनर के साथ आया था।

अधिकांश उपयोग के मामलों पर ध्यान दें, एक Tryसरल इंटरफ़ेस है, ऊपर दिए गए अधिकांश लाभ हैं, और आमतौर पर आपकी आवश्यकताओं को भी पूरा करता है। एक Optionऔर भी आसान है अगर आप परवाह करते हैं कि सफलता या विफलता है और विफलता के मामले में त्रुटि संदेश जैसी किसी भी राज्य की जानकारी की आवश्यकता नहीं है।

मेरे अनुभव में, Eithersवास्तव में Trysतब तक पसंद नहीं किया जाता है जब तक कि Leftएक Exception, शायद एक सत्यापन त्रुटि संदेश के अलावा कुछ और हो, और आप Leftमूल्यों को एकत्र करना चाहते हैं। उदाहरण के लिए, आप कुछ इनपुट संसाधित कर रहे हैं और आप सभी त्रुटि संदेशों को एकत्र करना चाहते हैं , न कि केवल पहले एक त्रुटि पर। वे स्थितियां बहुत बार व्यवहार में नहीं आती हैं, कम से कम मेरे लिए।

ट्राइ-कैच मॉडल से परे देखें और आप के Eithersसाथ काम करने के लिए और अधिक सुखद पाएंगे ।

अद्यतन: इस प्रश्न पर अभी भी ध्यान दिया जा रहा है, और मैंने वाक्य रचना के प्रश्न को स्पष्ट करते हुए ओपी के अपडेट को नहीं देखा था, इसलिए मैंने सोचा कि मैं और जोड़ूंगा।

अपवाद मानसिकता से बाहर निकलने के एक उदाहरण के रूप में, यह है कि मैं आमतौर पर आपका उदाहरण कोड लिखूंगा:

def compute(): Either[String, Int] = {
  Right(someSeq)
    .filterOrElse(someACondition,            "someACondition failed")
    .filterOrElse(_ forall someSeqCondition, "someSeqCondition failed")
    .map(_ map {_.toInt})
    .filterOrElse(_.sum <= 22, "Sum is greater than 22")
    .map(compute("good",_))
}

यहां आप देख सकते हैं कि filterOrElseहम इस फ़ंक्शन में मुख्य रूप से जो कुछ भी कर रहे हैं , उसे पूरी तरह से कैप्चर करते हैं: स्थितियों की जाँच करना और दिए गए विफलताओं के साथ त्रुटि संदेशों को जोड़ना। चूंकि यह एक बहुत ही सामान्य उपयोग का मामला है, filterOrElseमानक पुस्तकालय में है, लेकिन यदि ऐसा नहीं था, तो आप इसे बना सकते हैं।

यह वह बिंदु है जहां कोई व्यक्ति एक काउंटर-उदाहरण के साथ आता है जिसे ठीक उसी तरह से हल नहीं किया जा सकता है जैसा कि मेरा है, लेकिन मैं जिस बिंदु को बनाने की कोशिश कर रहा हूं वह Eithersअपवादों के विपरीत उपयोग करने का सिर्फ एक तरीका नहीं है। किसी भी त्रुटि से निपटने की स्थिति के लिए कोड को सरल बनाने के तरीके हैं, यदि आप उपयोग करने के लिए उपलब्ध सभी कार्यों का पता लगाते Eithersहैं और प्रयोग के लिए खुले हैं।


1. tryऔर catchएक अलग तर्क करने में सक्षम होने के नाते , लेकिन यह आसानी से हासिल नहीं किया जा सकता है Try? 2. Eitherडेटा संरचनाओं में भंडारण एस throwsतंत्र के साथ किया जा सकता है ; यह विफलताओं को संभालने के शीर्ष पर एक अतिरिक्त परत नहीं है? 3. आप निश्चित रूप से Exceptionएस का विस्तार कर सकते हैं । निश्चित रूप से, आप try-catchसंरचना को बदल नहीं सकते हैं , लेकिन विफलताओं से निपटना इतना आम है कि मैं निश्चित रूप से चाहता हूं कि भाषा मुझे इसके लिए एक बॉयलरप्लेट दे (जिसे मैं उपयोग करने के लिए मजबूर नहीं हूं)। यह कहने जैसा है कि इसके लिए समझदारी खराब है क्योंकि यह उन्मादी संचालन के लिए एक बॉयलरप्लेट है।
ईयाल रोथ

मुझे बस एहसास हुआ कि आपने कहा कि Eitherबढ़ाया जा सकता है, जहां स्पष्ट रूप से वे ( sealed traitकेवल दो कार्यान्वयन, दोनों के साथ final) नहीं कर सकते हैं । क्या आप इसे विस्तार में बताने में सक्षम हैं? मैं मान रहा हूँ कि आप का अर्थ नहीं है कि विस्तार का शाब्दिक अर्थ है।
ईयाल रोथ

1
मेरा अभिप्राय अंग्रेजी शब्द की तरह है, न कि प्रोग्रामिंग कीवर्ड। सामान्य पैटर्न को संभालने के लिए फ़ंक्शन बनाकर कार्यक्षमता को जोड़ना।
कार्ल

8

दोनों वास्तव में बहुत अलग हैं। Eitherकेवल संभावित विफलताओं का प्रतिनिधित्व करने के लिए शब्दार्थ बहुत अधिक सामान्य हैं।

Eitherआपको दो अलग-अलग प्रकारों में से एक को वापस करने की अनुमति देता है। बस।

अब, उन दो प्रकारों में से एक त्रुटि का प्रतिनिधित्व कर सकता है या नहीं और दूसरा सफलता का प्रतिनिधित्व कर सकता है या नहीं भी कर सकता है, लेकिन यह कई का केवल एक संभव उपयोग मामला है। Eitherउससे कहीं अधिक सामान्य है। आपके पास बस एक विधि हो सकती है जो उस उपयोगकर्ता के इनपुट को पढ़ती है जिसे या तो एक नाम दर्ज करने की अनुमति है या एक तारीख रिटर्न ए Either[String, Date]

या, C think में लंबोदर शाब्दिक के बारे में सोचें: वे या तो एक Funcया एक का Expressionमूल्यांकन करते हैं, यानी वे या तो एक अनाम फ़ंक्शन का मूल्यांकन करते हैं या वे एक एएसटी का मूल्यांकन करते हैं। C In में, यह "जादुई रूप से" होता है, लेकिन यदि आप इसे एक उचित प्रकार देना चाहते हैं, तो यह होगा Either<Func<T1, T2, …, R>, Expression<T1, T2, …, R>>। हालांकि, दोनों विकल्पों में से कोई भी एक त्रुटि नहीं है, और दोनों में से कोई भी "सामान्य" या "असाधारण" नहीं है। वे केवल दो अलग-अलग प्रकार हैं जो एक ही फ़ंक्शन (या इस मामले में, एक ही शाब्दिक के लिए निर्दिष्ट) से वापस आ सकते हैं। [नोट: वास्तव में, Funcएक और दो मामलों में विभाजित किया जाना है, क्योंकि C have में एक Unitप्रकार नहीं है , और इसलिए कुछ भी जो कुछ वापस नहीं करता है उसे उसी तरह से प्रतिनिधित्व नहीं किया जा सकता है जैसे कि कुछ वापस करता है,Either<Either<Func<T1, T2, …, R>, Action<T1, T2, …>>, Expression<T1, T2, …, R>>

अब, एक सफलता प्रकार और एक विफलता प्रकार का प्रतिनिधित्व करने के लिए इस्तेमाल किया Either जा सकता है। और यदि आप दो प्रकारों के सुसंगत क्रम पर सहमत हैं, तो आप दो प्रकारों में से एक को प्राथमिकता देने के लिए पूर्वाग्रह भी कर सकते Eitherहैं, इस प्रकार यह संभव है कि विमुद्रीकरण के माध्यम से विफलताओं को फैलाना संभव हो। लेकिन उस मामले में, आप एक निश्चित शब्दार्थ प्रदान कर रहे हैं Eitherकि यह आवश्यक रूप से अपने दम पर नहीं है।

एक Eitherजिसके पास अपने दो प्रकारों में से एक त्रुटि प्रकार निर्धारित किया गया है और त्रुटियों को फैलाने के लिए एक पक्ष के पक्षपाती है, को आमतौर पर एक Errorसनक कहा जाता है , और संभावित असफल गणना का प्रतिनिधित्व करने के लिए एक बेहतर विकल्प होगा। स्काला में, इस प्रकार का कहा जाता है Try

इसके साथ अपवाद के उपयोग की तुलना करने के भी बहुत कुछ समझ में आता है Tryके साथ तुलना में Either

तो, यह कारण है # 1 क्यों Eitherचेक अपवादों पर इस्तेमाल किया जा सकता है: Eitherअपवादों की तुलना में बहुत अधिक सामान्य है। इसका उपयोग उन मामलों में किया जा सकता है जहां अपवाद भी लागू नहीं होते हैं।

हालाँकि, आप सबसे अधिक संभावना सीमित मामले के बारे में पूछ रहे थे जहाँ आप अपवादों के प्रतिस्थापन के रूप में सिर्फ Either(या अधिक संभावना Try) का उपयोग करते हैं। उस स्थिति में, अभी भी कुछ फायदे हैं, या अलग-अलग दृष्टिकोण संभव हैं।

मुख्य लाभ यह है कि आप त्रुटि से निपटने को टाल सकते हैं। आप सिर्फ रिटर्न वैल्यू स्टोर करते हैं, बिना यह देखे भी कि यह सफलता है या कोई त्रुटि। (इसे बाद में संभाल लें।) या इसे कहीं और से पारित करें। (किसी और को इसके बारे में चिंता करने दें।) उन्हें एक सूची में इकट्ठा करें। (एक ही बार में उन सभी को संभालें।) आप उन्हें प्रसंस्करण पाइपलाइन के साथ प्रचारित करने के लिए मोनैडिक चेनिंग का उपयोग कर सकते हैं।

अपवादों के शब्दार्थ भाषा में कठोर हैं। उदाहरण के लिए स्काला में, अपवाद स्टैक को खोलते हैं। यदि आप उन्हें एक अपवाद हैंडलर तक बुलबुला करने देते हैं, तो हैंडलर वापस नहीं हो सकता है जहां यह हुआ और इसे ठीक कर दिया। OTOH, यदि आप इसे कम करने से पहले स्टैक में कम पकड़ते हैं और इसे ठीक करने के लिए आवश्यक संदर्भ को नष्ट करते हैं, तो आप एक घटक में हो सकते हैं जो आगे बढ़ने के बारे में एक सूचित निर्णय लेने के लिए बहुत कम-स्तर है।

यह स्मालटाक में अलग है, उदाहरण के लिए, जहां अपवाद स्टैक नहीं करते हैं और पुन: प्रारंभ योग्य हैं, और आप ढेर (संभवतः डिबगर के रूप में उच्च के रूप में) में अपवाद उच्च रह सकते हैं, waaaaayyyyy त्रुटि को ठीक नीचे में स्टैक और निष्पादन को फिर से शुरू करें। या कॉमन लिस्प की स्थिति जहां अपवादों के साथ दो (उठाना और पकड़ना) के बजाय उठाना, पकड़ना और संभालना तीन अलग-अलग चीजें हैं।

एक अपवाद के बजाय एक वास्तविक त्रुटि वापसी प्रकार का उपयोग करने से आप भाषा को संशोधित किए बिना, इसी तरह की चीजें और अधिक करने की अनुमति देते हैं।

और फिर कमरे में स्पष्ट हाथी है: अपवाद एक साइड-इफेक्ट हैं। दुष्परिणाम बुरे हैं। नोट: मैं यह नहीं कह रहा हूं कि यह जरूरी सच है। लेकिन यह कुछ लोगों के पास एक दृष्टिकोण है, और उस मामले में, अपवादों पर एक त्रुटि प्रकार का लाभ स्पष्ट है। इसलिए, यदि आप कार्यात्मक प्रोग्रामिंग करना चाहते हैं, तो आप एकमात्र कारण के लिए त्रुटि प्रकार का उपयोग कर सकते हैं कि वे कार्यात्मक दृष्टिकोण हैं। (ध्यान दें कि हास्केल के पास अपवाद हैं। ध्यान दें कि कोई भी उनका उपयोग करना पसंद नहीं करता है।)


उत्तर से प्यार करें, हालाँकि मुझे अभी भी यह नहीं दिखाई दे रहा है कि मुझे क्यों भूल जाना चाहिए ExceptionEitherएक महान उपकरण की तरह लगता है, लेकिन हां, मैं विशेष रूप से विफलताओं से निपटने के बारे में पूछ रहा हूं, और मैं अपने सभी कार्य के लिए एक अधिक शक्तिशाली उपकरण का उपयोग करूंगा। असफलता को सँभालना एक उचित तर्क है, लेकिन कोई भी Tryइस पद्धति का उपयोग कर सकता है, Exceptionयदि वह इस समय इसे नहीं संभालना चाहता है। क्या स्टैक-ट्रेस अनइंडिंग प्रभावित Either/ Tryसाथ ही नहीं करता है? गलत तरीके से प्रचार करने पर आप वही गलतियाँ दोहरा सकते हैं; एक विफलता को संभालने के लिए जानना दोनों ही मामलों में मामूली नहीं है।
इल रोथ

और मैं वास्तव में "विशुद्ध रूप से कार्यात्मक" तर्क के साथ बहस नहीं कर सकता, क्या मैं नहीं कर सकता?
इल रोथ

0

अपवादों के बारे में अच्छी बात यह है कि मूल कोड ने पहले से ही आपके लिए असाधारण परिस्थितियों को वर्गीकृत किया है। एक IllegalStateExceptionऔर एक के बीच BadParameterExceptionका अंतर मजबूत टाइप की गई भाषाओं में अंतर करना बहुत आसान है। यदि आप "अच्छा" और "बुरा" को पार्स करने की कोशिश करते हैं, तो आप अपने निपटान में स्कैब कंपाइलर पर बेहद शक्तिशाली उपकरण का लाभ नहीं उठा रहे हैं। अपने स्वयं के एक्सटेंशन Throwableपाठ संदेश स्ट्रिंग के अलावा, जितनी आवश्यक हो उतनी जानकारी शामिल कर सकते हैं।

यह Tryस्काला पर्यावरण की सच्ची उपयोगिता है, जिसमें Throwableजीवन को आसान बनाने के लिए बाईं वस्तुओं के आवरण के रूप में कार्य किया गया है।


2
मुझे आपकी बात समझ में नहीं आती।
इल रोथ

Eitherशैली के मुद्दे हैं क्योंकि यह एक सच्चा सन्यासी (?) नहीं है; leftजब आप उचित संरचना में असाधारण स्थितियों के बारे में जानकारी ठीक से संलग्न करते हैं तो मूल्य की मनमानी उच्च मूल्य से दूर हो जाती है। तो Eitherएक मामले के उपयोग की तुलना बाईं ओर के तारों को लौटाने try/catchमें, दूसरे मामले में ठीक से टाइप किए गए Throwables का उपयोग करना उचित नहीं है। Throwablesजानकारी प्रदान करने के लिए मूल्य के कारण , और संक्षिप्त तरीका जो Tryसंभालता है Throwables, या Tryतो उससे बेहतर शर्त है ... Eitherयाtry/catch
BobDalgleish

मैं वास्तव में चिंतित नहीं हूं try-catch। जैसा कि प्रश्न में कहा गया है कि बाद वाला मुझे बहुत साफ दिखता है, और दोनों मामलों में विफलता को संभालने वाला कोड (या तो पैटर्न-मैचिंग या तो या कैच) बहुत स्पष्ट है।
ईयाल रोथ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.