CATCH ब्लॉक में अपवाद और विफलता के बीच अंतर [RAKU]


9

हम जानते हैं कि एक विफलता को एक CATCH ब्लॉक द्वारा नियंत्रित किया जा सकता है।

निम्नलिखित उदाहरण में हम एक 'एडहॉक' विफलता (अन्य उप में) बनाते हैं और हम एक CATCH ब्लॉक (मेरे उप में) में अपवाद को संभालते हैं

sub my-sub {
    try {
        CATCH {
            when X::AdHoc { say 'AdHoc Exception handled here'; .resume }
            default {say 'Other Exception'; .resume}
        }

        my $b = other-sub();

        $b.so ?? $b.say !! 'This was a Failure'.say;
    }
}

sub other-sub { fail 'Failure_X' }

my-sub();

आउटपुट निम्नलिखित है:

AdHoc Exception handled here
This was a Failure

मेरा सवाल यह है कि: हम दो मामलों के बीच अंतर करने के लिए CATCH ब्लॉक में विफलता और "सामान्य" अपवाद के बीच अंतर कैसे कर सकते हैं?

जवाबों:


12

के बीच संबंध है Failureऔर Exceptionयह है कि एक Failureहै Exception- कि कहने के लिए है, यह अपने राज्य के हिस्से के रूप में अपवाद वस्तु रखती है। कुछ इस तरह:

class Failure {
    has Exception $.exception;
    # ...
}

जब एक Failure"विस्फोट" होता है, तो वह ऐसा करके फेंक देता है Exceptionजो उसके अंदर होता है। इस प्रकार, जो CATCHब्लॉक तक पहुंचता है वह Exceptionवस्तु है, और एनक्लोजिंग के लिए कोई लिंक वापस नहीं है Failure। (वास्तव में, किसी दिए गए Exceptionऑब्जेक्ट को कई Failureएस द्वारा आयोजित किया जा सकता है ।)

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

पूर्णता के लिए, मैं वहाँ है कि ध्यान दें जाएगा रहे हैं अप्रत्यक्ष तरीके से एक का पता लगा सकते है कि कि Exceptionएक से फेंक दिया गया था Failure। उदाहरण के लिए, यदि आप .backtraceअपवाद ऑब्जेक्ट को प्राप्त करते हैं और शीर्ष फ्रेम के पैकेज को देखते हैं, तो यह निर्धारित करना संभव है कि यह Failureनिम्न से आता है :

sub foo() { fail X::AdHoc.new(message => "foo") }
try {
    foo();
    CATCH {
        note do { no fatal; .backtrace[0].code.package ~~ Failure };
        .resume
    }
}

हालाँकि, यह बहुत हद तक कार्यान्वयन विवरण पर निर्भर है जो आसानी से बदल सकता है, इसलिए मैं इस पर भरोसा नहीं करता।


बस चीजों को स्पष्ट करने के लिए, मेरा इरादा केवल अपवाद (CATCH ब्लॉक में) के लिए संभालना है। एक विफलता के मामले में मैं फिर से शुरू करना चाहता हूं जैसे कि कुछ भी नहीं हुआ और बाकी कोड (CATCH के बाहर) को विफल होने दें। मेरे उदाहरण में मुझे निहित अपवाद को ट्रिगर करने में विफल विफलता की उम्मीद नहीं थी! मैंने केवल $ b में परिणाम प्राप्त किया और इसे बूल के रूप में जांचा। मेरे विचार में, असफलता के "उपयोग" का गठन नहीं करता है और इसलिए यह CATCH ब्लॉक को ट्रिगर करता है! इसके बजाय ऐसा लगता है कि CATCH हमेशा विफलता में निहित अपवाद को संभाल रहा है !!
जाकर

इसके अलावा आपके उदाहरण में, एक विफलता का पता लगाने के अप्रत्यक्ष तरीके के बारे में, लौटाया गया बूल (स्मार्ट चेकिंग से विफलता प्रकार) मूल्य "गलत" है। लेकिन मुझे उम्मीद थी कि यह "सच" होगा! क्या मैं कुछ भुल गया???
जाकर

1
@ जकर एक tryब्लॉक का अर्थ है प्रज्ञा use fatal, जिसका अर्थ Failureहै कि ब्लॉक में की गई कॉल से लौटा कोई भी तुरंत अपवाद में बदल जाता है। बस का उपयोग न करें try; एक CATCHरकु में किसी भी ब्लॉक में जा सकता है (इसलिए बस उसके स्तर पर है sub)। वैकल्पिक रूप से, no fatalअपने tryब्लॉक के शीर्ष पर लिखें ।
जोनाथन वर्थिंगटन

और मेरी दूसरी टिप्पणी के बारे में क्या?
जकर

1
उदाहरण के तौर Trueपर मैंने स्थानीय स्तर पर रकोडो संस्करण पर प्रिंट दिए । यदि यह आप पर नहीं है, तो बस ऐसा करने की नाजुकता के बारे में बात साबित होती है।
जोनाथन वर्थिंगटन

6

बस tryआवरण हटा दें :

sub my-sub {

#    try {              <--- remove this line...

        CATCH {
            when X::AdHoc { say 'AdHoc Exception handled here'; .resume }
            default {say 'Other Exception'; .resume}
        }

        my $b = other-sub();

        $b.so ?? $b.say !! 'This was a Failure'.say;

#    }                  <--- ...and this one

}

sub other-sub { fail 'Failure_X' }

my-sub();

आपने उपयोग किया try। A tryकुछ चीजें करता है, लेकिन यहां एक खास बात यह है कि यह Raku Failureको अपवादों के दायरे में किसी भी s को तुरंत बढ़ावा देने के लिए कहता है - जो आप कहते हैं कि आप नहीं चाहते हैं। तो सबसे सरल उपाय यह है कि बस करना बंद कर दें।


यह उत्तर सिर्फ jnthn की व्याख्या का हिस्सा है। लेकिन मुझे यकीन नहीं था कि सभी पाठक इस पहलू को जानेंगे / समझेंगे, और मुझे नहीं लगा कि jnthn के उत्तर पर एक टिप्पणी या दो मदद मिलेगी, इसलिए यह उत्तर है।

मैंने यह सुनिश्चित करने के लिए एक सामुदायिक उत्तर के रूप में लिखा है कि मैं किसी भी अपवित्र से लाभ नहीं उठाऊंगा क्योंकि यह स्पष्ट रूप से वारंट नहीं करता है। यदि यह पर्याप्त डाउनवोट हो जाता है तो हम इसे हटा देंगे।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.