2014-09-04 11 views
7

मैं स्कैला में फ्यूचर्स चेन करने की कोशिश कर रहा हूं लेकिन यह मुझे गलत रिटर्न प्रकार दे रहा है।चेन स्कैला फ्यूचर्स रिटर्न टाइप

मेरे पास निम्न विधियों:

def getOneRecordByModel(x:DirectFlight): Future[Option[FlightByDetailModel]] = { 
    select.allowFiltering().where(_.from eqs x.from).and(_.to eqs x.to).and(_.departure eqs x.departure).and(_.arrival eqs x.arrival).and(_.carrier eqs x.airline).and(_.code eqs x.flightCode).one() 
    } 
    def getRecordByUUID(x:FlightByDetailModel): Future[Option[FlightByUUIDModel]] = { 
    select.allowFiltering().where(_.uuid eqs x.uuid).one() 
    } 

    def getUUIDRecordByModel(x:DirectFlight): Future[Option[FlightByUUIDModel]] = { 
     getOneRecordByModel(x) andThen { 
     case Success(Some(flight)) => getRecordByUUID(flight) 
     case Success(x) => Success(x) 
     case Failure(x) => Failure(x) 
     } 
    } 

लेकिन अब मुझे लगता है कि getUUIDRecordByModel वापसी प्रकार Future[Option[FlightByDetailModel]]

है मैं कैसे उन्हें सही ढंग से श्रृंखला है त्रुटि मिलती है?

+0

जब आप उपयोग करते हैं और तब आप रिटर्न प्रकार नहीं बदलते हैं। आप अन्य विधि के रिटर्न प्रकार के आधार पर फ्लैटमैप या मानचित्र चाहते हैं। – monkjack

+2

'और तेन' संयोजक पूरी तरह से साइड इफेक्टिंग के लिए है। यह हमेशा 'भविष्य' देता है जिसे इसे अपरिवर्तित कहा जा रहा है। जैसा कि दूसरों द्वारा उल्लिखित किया गया है, 'मानचित्र' और/या 'flatMap' जो आप खोज रहे हैं वह होना चाहिए। – cmbaxter

उत्तर

8

मैं इसके बजाय flatMap का उपयोग करूंगा।

def getUUIDRecordByModel(x:DirectFlight): Future[Option[FlightByUUIDModel]] = { 
    getOneRecordByModel(x) flatMap { 
     case Some(flight) => getRecordByUUID(flight) 
     case None => Future.successful(None) 
    } 
} 

andThen एक पक्ष प्रभावशाली समारोह लागू होता है और मूलFuture, नहीं आंतरिक एक देता है।

+0

यह है। आपका बहुत बहुत धन्यवाद! – elmalto

3

आप इसे स्कालाज़ मोनैड ट्रांसफार्मर, विकल्प टी के साथ विशेष रूप से कर सकते हैं। http://noelwelsh.com/programming/2013/12/20/scalaz-monad-transformers/

def getOneRecordByModel(x:DirectFlight): Future[Option[FlightByDetailModel]] = ??? 
    def getRecordByUUID(x:FlightByDetailModel): Future[Option[FlightByUUIDModel]] = ??? 

    def getUUIDRecordByModel(x:DirectFlight): Future[Option[FlightByUUIDModel]] = { 
    import scalaz.OptionT._ 

    val flightByUUID = for { 
     flightByDetailModel <- optionT(getOneRecordByModel(x)) 
     flightByUUIDModel <- optionT(getRecordByUUID(flightByDetailModel)) 
    } yield flightByUUIDModel 

    flightByUUID.run 
    } 

scala.concurrent.Future साथ optionT उपयोग करने के लिए आप functor जरूरत है सक्षम होने के लिए: http://eed3si9n.com/learning-scalaz/Monad+transformers.html#Monad+transformers

यह एक अच्छी बात है: आप ईख लेख के अच्छा सेट, और अधिक विशिष्ट आप इस एक की जरूरत है सकते हैं और इकाई उदाहरणों दायरे में होना करने के लिए

import scala.concurrent.Future 

    object FutureMonadAndFunctor { 

    import scalaz.Monad 

    implicit def FutureM(implicit ec: ExecutionContext): Monad[Future] = new Monad[Future] { 
     def point[A](a: => A): Future[A] = Future(a) 
     def bind[A, B](fa: Future[A])(f: (A) => Future[B]): Future[B] = fa flatMap f 
    } 

    implicit def FutureF(implicit ec: ExecutionContext): Functor[Future] = new Functor[Future]{ 
     def map[A, B](fa: Future[A])(f: (A) => B): Future[B] = fa map f 
    } 
    } 

    import scala.concurrent.ExecutionContext.Implicits.global 

    implicit val F = FutureMonadAndFunctor.FutureF 
    implicit val M = FutureMonadAndFunctor.FutureM 
+0

अंतर्दृष्टि के लिए धन्यवाद। मैं अब कई बार स्कालज़ में आया हूं। मुझे लगता है कि मेरे लिए कुछ अध्ययन करने का समय है। – elmalto

2

एक सरल समाधान andthen के बजाय रचना है, जो दुष्प्रभाव से निपटने के लिए नहीं बल्कि विशेष है के लिए flatMap उपयोग करने के लिए है:

getOneRecordByModel(x) flatMap { 
    ... 
} 

वायदा के साथ काम करने के लिए, मुझे कई बार this page पढ़ने में मदद मिली।

5

यह समाधान और इसके ऊपर 2, प्रभावी रूप से समान हैं। वे फ्लैटमैप्स की संरचना का सरल जवाब सुझाते हैं। यह एक-ऑफ समाधान के लिए अच्छा है।

for { 
    oUuid <- getOneRecordByModel(x) 
    oFlight <- oUuid.map(getRecordByUUID).getOrElse(Future.successful(None)) 
} yield oFlight 

मुझे विधि हस्ताक्षर दिए जाने पर संदेह है, तो आप इस रणनीति का बहुत उपयोग कर रहे हैं। यदि ऐसा है, तो @Eugene Zhulenev का उत्तर ऊपर (जो एक अधिक कार्यात्मक समाधान है) की सिफारिश की जाती है। सोचा इकाई ट्रांसफॉर्मर एक सा पहली नजर में डराना देख सकते हैं, कोड का हिस्सा यहाँ:

val flightByUUID = for { 
    flightByDetailModel <- optionT(getOneRecordByModel(x)) 
    flightByUUIDModel <- optionT(getRecordByUUID(flightByDetailModel)) 
} yield flightByUUIDModel 

flightByUUID.run // this line grabs you a Future[Option[T]] 

बहुत ही सरल, और स्केलेबल है के रूप में आप जटिलता जोड़ना शुरू करें। उम्मीद है कि यह आपकी मदद करता है।

+0

काम करता है साथ ही आपको बहुत धन्यवाद। दुर्भाग्यवश मैं केवल एक उत्तर को सही के रूप में चुन सकता हूं। – elmalto

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