2013-07-25 11 views
21

उदाहरण में के लिए नीचे मैं अपवाद java.util.NoSuchElementException: Future.filter predicate is not satisfiedस्काला भविष्य में समझ

मिल रहा जब जांच if(i == 2) विफल रहता परिणाम Future(Test2) करना चाहते हैं फिल्टर के साथ। मैं फ़िल्टर को कैसे संभाल सकता/सकती हूं अगर समझने के लिए वायदा वायदा से संबंधित है?

नीचे एक सरलीकृत उदाहरण है जो स्कैला आरईपीएल में काम करता है।

कोड:

import scala.concurrent.Future 
import scala.util.{ Try, Success, Failure } 
import scala.concurrent.ExecutionContext.Implicits.global 

val f1 = Future(1) 
val f2 = for { 
    i <- f1 
    if(i == 2) 
} yield "Test1" 
f2.recover{ case _ => "Test2" } 
f2.value 

उत्तर

11

अपने for-comprehension में, आप i == 2 द्वारा फ़िल्टर कर रहे हैं। चूंकि f1 का मान दो नहीं है, इसलिए यह Success नहीं मिलेगा बल्कि इसके बजाय Failure होगा। फ़िल्टर का पूर्वानुमान संतुष्ट नहीं है, क्योंकि आपका त्रुटि संदेश आपको बताता है। हालांकि, f2.recover एक नया Future देता है। f2 का मान छेड़छाड़ नहीं किया गया है। यह अभी भी Failure स्टोर करता है। जब आप f2.value पर कॉल करते हैं तो आपको त्रुटि संदेश मिलता है।

एकमात्र विकल्प जिसे मैं सोच सकता हूं else आपके for-comprehension में दिखाया जाएगा जैसा कि here दिखाया गया है।

val f2 = for (i <- f1) yield { 
    if (i == 2) "Test1" 
    else "Test2" 
} 
f2.value 

इस रूप में अपने f3.value करता Some(Success(Test2)) वापस आ जाएगी।

+0

हालांकि अगर "2 <- f1" विफल होने के कारण f2 विफल रहता है, तो परिणाम "टेस्ट 2" नहीं होगा लेकिन फिर भी विफलता होगी। –

8

बेशक मैं बाहर एक समाधान अपने आप लगा। शायद बेहतर, अधिक मूर्खतापूर्ण, समाधान हैं?

import scala.concurrent.Future 
import scala.util.{ Try, Success, Failure } 
import scala.concurrent.ExecutionContext.Implicits.global 

val f1 = Future(1) 
val f2 = for { 
    i <- f1 
    if(i == 2) 
} yield "Test1" 
val f3 = f2.recover{ case _ => "Test2" } 
// OR val f3 = f2.fallbackTo(Future("Test2")) 
f3.value 
+1

यह डॉक्स में उल्लेख किया है और साथ ही: http://docs.scala-lang.org/overviews/core/futures.html#functional_composition_and_forcomprehensions नहीं जब मैं एक दूसरा रूप लेता हूं। – Magnus

+1

मुझे लगता है कि यहां 'पुनर्प्राप्ति' का उपयोग करना ठीक है। यदि आप चाहते हैं कि आपकी पुनर्प्राप्ति केवल फ़िल्टर पूर्वानुमान आधारित अपवाद पर लागू हो, तो आपको 'केस _' से' केस पूर्व: NoSuchElementException' को बदलना चाहिए जहां 'NoSuchElementException'' java.util' से आता है। – cmbaxter

+0

जुर्गन: यह एक छः महीने का सवाल है, ऊपर दिया गया कोड आरईपीएल सत्र से लिया गया एक उदाहरण था, इसलिए यह स्पष्टता की ओर तैयार है। आप इस पर टिप्पणी कर रहे हैं कि आप स्कैला में बयान के आसपास कोष्ठक डाल सकते हैं? यह नहीं देख रहा कि आपका योगदान क्या है। – Magnus

27

यह मेरी राय में एक और मूर्खतापूर्ण समाधान है। यह अनुमानित फ़ंक्शन या तो Future[Unit] या आपके अपवाद वाले असफल भविष्य को बनाता है। आपके उदाहरण के लिए, इसका परिणाम Success("Test1") या Failure(Exception("Test2")) होगा। यह "टेस्ट 1" और "टेस्ट 2" से थोड़ा अलग है, लेकिन मुझे यह वाक्यविन्यास अधिक उपयोगी होने लगता है।

def predicate(condition: Boolean)(fail: Exception): Future[Unit] = 
    if (condition) Future(()) else Future.failed(fail) 

आप इस तरह इसका इस्तेमाल:

val f2 = for { 
    i <- f1 
    _ <- predicate(i == 2)(new Exception("Test2")) 
    j <- f3 // f3 will only run if the predicate is true 
} yield "Test1" 
+1

यह बहुत उपयोगी सलाह थी। धन्यवाद! – Tommi

+0

बहुत स्पष्ट, धन्यवाद! – Artemis

संबंधित मुद्दे