2009-04-19 8 views
28

मैं एक बंद से वापस लौटना चाहूंगा, जैसे कि एक लूप में ब्रेक स्टेटमेंट का उपयोग करना होगा।कोई ग्रोवी बंद होने से कैसे लौटता है और इसके निष्पादन को रोकता है?

उदाहरण के लिए:

largeListOfElements.each{ element-> 
    if(element == specificElement){ 
     // do some work   
     return // but this will only leave this iteration and start the next 
    } 
} 

ऊपर में अगर बयान मैं सूची के माध्यम से पुनरावृत्ति रोकने के लिए और बंद छोड़ अनावश्यक पुनरावृत्तियों से बचने के लिए करना चाहते हैं।

मैं एक समाधान जहां एक अपवाद बंद भीतर फेंक दिया और बाहर पकड़ा है देखा है, लेकिन मुझे लगता है कि समाधान के भी शौकीन नहीं हूँ।

क्या इस तरह के एल्गोरिदम से बचने के लिए कोड बदलने के अलावा इसके कोई समाधान हैं?

उत्तर

24

मुझे लगता है कि आप प्रत्येक के बजाय (कम से कम निर्दिष्ट उदाहरण के लिए) का उपयोग करना चाहते हैं। क्लोजर सीधे ब्रेक का समर्थन नहीं करते हैं।

कवर के तहत, ग्रूवी वास्तव में पाश के लिए एक बंद या तो खोजने के लिए, यह एक का उपयोग करता है का उपयोग नहीं करता।

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

यहाँ एक उदाहरण है:

 
Object.metaClass.eachBreak = { ifClosure, workClosure -> 
    for (Iterator iter = delegate.iterator(); iter.hasNext();) { 
     def value = iter.next() 
     if (ifClosure.call(value)) { 
      workClosure.call(value) 
      break 
     }   
    } 
} 

def a = ["foo", "bar", "baz", "qux"] 

a.eachBreak({ it.startsWith("b") }) { 
    println "working on $it" 
} 

// prints "working on bar" 
2

मुझे लगता है कि आप अमूर्तता के गलत स्तर पर काम कर रहे हैं। .each ब्लॉक ठीक वही करता है जो यह कहता है: यह प्रत्येक तत्व के लिए एक बार बंद होने को निष्पादित करता है। इसके बजाय आप शायद List.indexOf का उपयोग specificElement ढूंढने के लिए करना चाहते हैं, और फिर उस कार्य को करें जो आपको करने की आवश्यकता है।

3

आप सभी तत्वों पर कार्रवाई करना चाहते हैं जब तक किसी एक को आप भी कुछ इस तरह कर सकता है पाया गया था:

largeListOfElements.find { element -> 
    // do some work 
    element == specificElement 
} 

आप किसी के साथ इस का उपयोग कर सकते हैं "ब्रेक हालत" की तरह। मैं सिर्फ यह प्रयोग किया जाता है बंद करने के अंत में

counter++ >= n 

प्रत्यावर्तित करके संग्रह की पहली n तत्वों पर कार्रवाई करने के।

1

मैं ग्रूवी को समझने के रूप में, जिस तरह से छोरों की इन प्रकार के शॉर्टकट के लिए एक उपयोगकर्ता परिभाषित अपवाद फेंकने के लिए होगा।मैं क्या वाक्य रचना होगा (नहीं एक grrovy प्रोग्रामर) पता नहीं है, लेकिन JVM पर ग्रूवी रन तो यह कुछ कुछ की तरह होगा:

class ThisOne extends Exception {Object foo; ThisOne(Object foo) {this.foo=foo;}} 

try { x.each{ if(it.isOk()) throw new ThisOne(it); false} } 
catch(ThisOne x) { print x.foo + " is ok"; }  
1

paulmurray के जवाब के बाद मैं अपने आप को सुनिश्चित नहीं किया गया था क्या होगा

class TestCaseForThrowingExceptionFromInsideClosure { 

    @Test 
    void testEearlyReturnViaException() { 
     try { 
      [ 'a', 'b', 'c', 'd' ].each {     
       System.out.println(it) 
       if (it == 'c') { 
        throw new Exception("Found c") 
       } 
      } 
     } 
     catch (Exception exe) { 
      System.out.println(exe.message) 
     } 
    } 
} 

ऊपर के उत्पादन में है: एक अपवाद को बंद करने के भीतर से फेंका, तो मैं एक JUnit टेस्ट केस के बारे में सोचने के लिए आसान है कि ऊपर मार पड़ी है

a 
b 
c 
Found c 

लेकिन वह याद "एक प्रवाह नियंत्रण के लिए अपवाद का उपयोग नहीं करना चाहिए", विशेष रूप से देखते हैं कि यह स्टैक ओवरफ़्लो प्रश्न: Why not use exceptions as regular flow of control?

तो ऊपर समाधान किसी भी मामले में आदर्श से कम है। बस का उपयोग करें:

class TestCaseForThrowingExceptionFromInsideClosure { 

    @Test 
    void testEarlyReturnViaFind() { 
     def curSolution 
     [ 'a', 'b', 'c', 'd' ].find {     
      System.out.println(it) 
      curSolution = it 
      return (it == 'c') // if true is returned, find() stops 
     } 
     System.out.println("Found ${curSolution}") 
    } 
} 

ऊपर के उत्पादन में भी है:

a 
b 
c 
Found c 
संबंधित मुद्दे