2015-04-16 4 views
7

documentation के अनुसार:या तो और विकल्प के बीच अंतर क्या हैं?

या तो की एक सामान्य उपयोग संभव लापता मूल्यों के साथ निपटने के लिए विकल्प के लिए एक विकल्प के रूप में है।

आप दूसरे पर एक का उपयोग क्यों करेंगे?

उत्तर

10

Either के बारे में अच्छी बात यह है कि आप कारण का कुछ ट्रैक खो सकते हैं। उदाहरण के लिए, यदि आप Options साथ काम कर रहे थे, तो आप इस तरह एक स्थिति में हो सकता है:

val xOpt = Option(1) 
val yOpt = Option(2) 
val zOpt = None 

val tupled = for { 
    x <- xOpt 
    y <- yOpt 
    z <- zOpt 
} yield (x, y, z) 

अब, अगर tupledNone है, हम वास्तव में पता नहीं क्यों! इस व्यवहार के बाकी के लिए एक महत्वपूर्ण विस्तार, Either का उपयोग कर मदद कर सकते हैं यह है:

val tupled = for { 
    x <- xOpt.toRight("x is missing").right 
    y <- yOpt.toRight("y is missing").right 
    z <- zOpt.toRight("z is missing").right 
} yield (x, y, z) 

यह या तो Left(msg) वापस आ जाएगी जहां संदेश पहले लापता मूल्य के लिए इसी संदेश, या tupled मूल्य के लिए Right(value) है। विफलताओं के लिए Left और सफलता के लिए Right का उपयोग करना पारंपरिक है।

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

val xTry = Try("1".toInt) 
val yTry = Try("2".toInt) 
val zTry = Try("asdf".toInt) 

val tupled = for { 
    x <- xTry 
    y <- yTry 
    z <- zTry 
} yield (x, y, z) 

Try[A]Either[Throwable, A] isomorphic को है:

तीसरे आम मुहावरा असाधारण मूल्यों के लिए उपयोग करने के लिए Try इकाई है। दूसरे शब्दों में आप Throwable के बाईं प्रकार के साथ एक Try एक Either के रूप में इलाज कर सकते हैं, और आप किसी भी Either एक Try रूप Throwable के बाईं प्रकार है कि इलाज कर सकते हैं। Option[A]Try[A] पर होमोमोर्फिक है। तो आप Option को Try के रूप में देख सकते हैं जो त्रुटियों को अनदेखा करता है। इसलिए आप इसे Either के रूप में भी सोच सकते हैं। वास्तव में, मानक पुस्तकालय इन परिवर्तनों में से कुछ का समर्थन करता है:

//Either to Option 
Left[Int, String](1).left.toOption //Some(1) 
Right[Int, String]("foo").left.toOption //None 

//Try to Option 
Try("1".toInt).toOption //Some(1) 
Try("foo".toInt).toOption //None 

//Option to Either 
Some(1).toRight("foo") //Right[String, Int](1) 
(None: Option[Int]).toRight("foo") //Left[String, Int]("foo") 

मानक पुस्तकालय रूपांतरण Either से Try को, Try से Either को शामिल नहीं करता है, या Option से Try करने के लिए। लेकिन यह आवश्यक रूप Option, Try, और Either को बेहतर बनाने के बहुत सरल है:

object OptionTryEitherConversions { 
    implicit class EitherToTry[L <: Throwable, R](val e: Either[L, R]) extends AnyVal { 
     def toTry: Try[R] = e.fold(Failure(_), Success(_)) 
    } 

    implicit class TryToEither[T](val t: Try[T]) extends AnyVal { 
     def toEither: Either[Throwable, T] = t.map(Right(_)).recover(PartialFunction(Left(_))).get 
    } 

    implicit class OptionToTry[T](val o: Option[T]) extends AnyVal { 
     def toTry(throwable: Throwable): Try[T] = o.map(Right(_)).getOrElse(Left(throwable)) 
    } 
} 

यह तुम क्या करने की अनुमति होगी:

import OptionTryEitherConversions._ 

//Try to Either 
Try(1).toEither //Either[Throwable, Int] = Right(1) 
Try("foo".toInt).toEither //Either[Throwable, Int] = Left(java.lang.NumberFormatException) 

//Either to Try 
Right[Throwable, Int](1).toTry //Success(1) 
Left[Throwable, Int](new Exception).toTry //Failure(java.lang.Exception) 

//Option to Try 
Some(1).toTry(new Exception) //Success(1) 
(None: Option[Int]).toTry(new Exception) //Failure(java.lang.Exception) 
6

EitherOption के सामान्यीकरण के रूप में देखा जा सकता है। आप Unit को निर्धारित कर उस उदाहरण के लिए Either के पहले मूल्य, ठीक हैं, तो आप कुछ है कि अनिवार्य रूप से Option के रूप में एक ही तरह से व्यवहार करती है मिलेगा:

Option[X] := Either[Unit, X] 

इस मामले में, Left[Unit, X]None के अनुरूप होता है, और Right[Unit, X]Some[X] के अनुरूप होगा।

Option[X] के लिए, None प्रकार X के एक मूल्य प्राप्त करने के लिए विफलता किसी तरह का संकेत होता है, और Some[X] सफलता का संकेत दिया। Either[Unit, X] के लिए, प्रकार Left[Unit, X] का उदाहरण विफलता का प्रतिनिधित्व करेगा, और Right[Unit, X] सफलता का प्रतिनिधित्व करेगा।

हालांकि, अगर आप क्यों कुछ विफल रहा है, या कुछ अतिरिक्त जानकारी आपको एक त्रुटि से उबरने के लिए मदद करता है कि बारे में विस्तृत जानकारी स्टोर करने के लिए Either के पहले घटक उपयोग कर सकते हैं। Option आपको सिर्फ None देता है, जो बहुत उपयोगी नहीं है। लेकिन Either[F,X] या तो सफलता मूल्य Right[F, X] लौटा सकता है, जो X के लिए अनिवार्य रूप से केवल एक रैपर है, या Left[F, X] में विफलता का विस्तृत विवरण, F प्रकार की विफलता का प्रतिनिधित्व करने के साथ।

यह आपको अधिक परिष्कृत वसूली रणनीतियों को परिभाषित करने की अनुमति देता है। उदाहरण के लिए, Play के Form.scala पर एक नज़र डालें! -फ्रेमवर्क। वे पूरे स्थान पर Either का उपयोग करते हैं, क्योंकि वे या तो उपयोगकर्ता के फॉर्म सबमिशन का जवाब देना चाहते हैं, या आंशिक रूप से भरे हुए फॉर्म को वापस भेजने के लिए, उपयोगी त्रुटि संदेशों के साथ एनोटेटेड हैं। इसका विकल्प Option[TypeOfFormContent] के साथ काम करना होगा, जो None का मूल्यांकन करेगा यदि कुछ फॉर्म फ़ील्ड में अमान्य इनपुट था। बदले में इसका मतलब यह होगा कि उपयोगकर्ता को "खराब अनुरोध" जैसे कुछ मिलता है। कृपया पूरा फॉर्म फिर से भरें। " प्रतिक्रिया के रूप में, जो पूरी तरह से परेशान होगा। इसलिए, का उपयोग Option के बजाय किया जाता है, क्योंकि यह वास्तव में फ़ॉर्म सबमिशन के साथ वास्तव में गलत होने का ट्रैक रख सकता है।

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

+1

एंड्री ट्यूकिन वापस आ गया है! मुझे हालांकि स्वीकार करना है- मैं थोड़ा निराश हूं कि आपने अपने उत्तर के लिए [एक और भयानक आरेख] (http://stackoverflow.com/a/19739576/1427124) एक साथ नहीं रखा है। – DaoWen

+1

@ दाओवेन: मुझे लगता है कि मुझे निश्चित रूप से अपने "इंटरनेट-एल्टर-अहो" के बारे में कुछ करना चाहिए, क्योंकि वर्तमान में ऐसा लगता है जैसे जलती हुई शाकाहारी पांडा का एक हास्यास्पद gif-painting मेरा सबसे महत्वपूर्ण विचार है। तीन महीने या उससे भी ज्यादा में इसके बारे में कुछ करने के लिए। –

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