खोज…


वाक्य - विन्यास

  • वर्ग कुछ [+ T] (मूल्य: T) विकल्प [T] बढ़ाता है

  • ऑब्जेक्ट कोई भी विकल्प नहीं बढ़ाता [कुछ भी नहीं]

  • विकल्प [टी] (मूल्य: टी)

    प्रदान किए गए मूल्य के लिए Some(value) या None उपयुक्त बनाने के लिए निर्माता।

संग्रह के रूप में विकल्प

Option s में कुछ उपयोगी उच्च-क्रम वाले कार्य होते हैं जिन्हें विकल्पों को शून्य या एक आइटम के साथ संग्रह के रूप में देखकर आसानी से समझा जा सकता है - जहां None खाली संग्रह की तरह व्यवहार None करता है, और Some(x) एकल आइटम, x साथ संग्रह की तरह व्यवहार करता है।

val option: Option[String] = ???

option.map(_.trim) // None if option is None, Some(s.trim) if Some(s)
option.foreach(println) // prints the string if it exists, does nothing otherwise
option.forall(_.length > 4) // true if None or if Some(s) and s.length > 4
option.exists(_.length > 4) // true if Some(s) and s.length > 4
option.toList // returns an actual list

अशक्त के बजाय विकल्प का उपयोग करना

जावा (और अन्य भाषाओं) में, null का उपयोग यह इंगित करने का एक सामान्य तरीका है कि संदर्भ चर से जुड़ा कोई मूल्य नहीं है। Scala में, null का उपयोग करके Option का उपयोग करना अधिक पसंद किया जाता है। Option उन मानों को लपेटता है जो null हो सकते हैं।

None एक शून्य संदर्भ लपेटते हुए Option का एक उपवर्ग है। Some Option एक गैर-शून्य संदर्भ को लपेटने का एक उपवर्ग है।

एक संदर्भ लपेटना आसान है:

val nothing = Option(null) // None
val something = Option("Aren't options cool?") // Some("Aren't options cool?")

जावा लाइब्रेरी को कॉल करते समय यह विशिष्ट कोड है जो एक अशक्त संदर्भ लौटा सकता है:

val resource = Option(JavaLib.getResource())
// if null, then resource = None
// else resource = Some(resource)

यदि getResource() एक null मान देता है, तो resource None ऑब्जेक्ट None होगा। अन्यथा यह Some(resource) वस्तु होगी। एक Option को संभालने का पसंदीदा तरीका Option प्रकार के भीतर उपलब्ध उच्च आदेश कार्यों का उपयोग करना है। उदाहरण के लिए यदि आप जांचना चाहते हैं कि क्या आपका मूल्य कोई None (यदि value == null जाँच के समान), तो आप isDefined फ़ंक्शन का उपयोग करेंगे:

val resource: Option[Resource] = Option(JavaLib.getResource())
if (resource.isDefined) {  // resource is `Some(_)` type
  val r: Resource = resource.get
  r.connect()
}

इसी तरह, एक null संदर्भ की जांच करने के लिए आप यह कर सकते हैं:

val resource: Option[Resource] = Option(JavaLib.getResource())
if (resource.isEmpty) { // resource is `None` type.
  System.out.println("Resource is empty! Cannot connect.")
}

बेहतर होगा कि आप एक का लिपटे मूल्य पर सशर्त निष्पादन का इलाज Option ( 'असाधारण' का उपयोग किए बिना Option.get इलाज विधि) Option एक इकाई के रूप में और का उपयोग कर foreach :

val resource: Option[Resource] = Option(JavaLib.getResource())
resource foreach (r => r.connect())
// if r is defined, then r.connect() is run
// if r is empty, then it does nothing

यदि Resource उदाहरण की आवश्यकता है (बनाम एक Option[Resource] उदाहरण), तो आप अभी भी अशक्त मूल्यों से बचाने के लिए Option का उपयोग कर सकते हैं। यहाँ getOrElse विधि एक डिफ़ॉल्ट मान प्रदान करती है:

lazy val defaultResource = new Resource()
val resource: Resource = Option(JavaLib.getResource()).getOrElse(defaultResource)

जावा कोड आसानी से स्काला के Option हैंडल नहीं करेगा, इसलिए जावा कोड में वैल्यूज को पास करते समय यह Option को अनफ्रेंड करने के लिए अच्छा फॉर्म है, null या एक समझदार डिफ़ॉल्ट जहां उपयुक्त हो:

val resource: Option[Resource] = ???
JavaLib.sendResource(resource.orNull)
JavaLib.sendResource(resource.getOrElse(defaultResource)) // 

मूल बातें

एक Option एक डेटा संरचना है जिसमें या तो एक ही मूल्य होता है, या बिल्कुल भी कोई मूल्य नहीं होता है। एक Option को शून्य या एक तत्वों के संग्रह के रूप में सोचा जा सकता है।

विकल्प दो बच्चों के साथ एक सार वर्ग है: Some और None

Some में एकल मान होता है, और None में कोई मान None होता है।

Option उन अभिव्यक्तियों में उपयोगी है जो अन्यथा एक ठोस मूल्य की कमी का प्रतिनिधित्व करने के लिए null का उपयोग करेंगे। यह एक NullPointerException विरुद्ध सुरक्षा करता है, और कई अभिव्यक्तियों की संरचना की अनुमति देता है, जो कॉम्बीनेटर जैसे कि Map , FlatMap , आदि का उपयोग करके कोई मान नहीं लौटा सकता है।

मानचित्र के साथ उदाहरण

val countries = Map(
  "USA" -> "Washington",
  "UK" -> "London",
  "Germany" -> "Berlin",
  "Netherlands" -> "Amsterdam",
  "Japan" -> "Tokyo"
)
    
println(countries.get("USA")) // Some(Washington)
println(countries.get("France")) // None
println(countries.get("USA").get) // Washington
println(countries.get("France").get) // Error: NoSuchElementException
println(countries.get("USA").getOrElse("Nope")) // Washington
println(countries.get("France").getOrElse("Nope")) // Nope

Option[A] को सील कर दिया जाता है और इस तरह बढ़ाया नहीं जा सकता। इसलिए यह शब्दार्थ स्थिर है और इस पर भरोसा किया जा सकता है।

समझ के लिए विकल्प

Option s में एक flatMap विधि है। इसका मतलब है कि वे एक समझ के लिए इस्तेमाल किया जा सकता है। इस तरह हम उन्हें फिर से परिभाषित किए बिना Option एस पर काम करने के लिए नियमित कार्यों को उठा सकते हैं।

val firstOption: Option[Int] = Option(1)
val secondOption: Option[Int] = Option(2)

val myResult = for {
  firstValue <- firstOption
  secondValue <- secondOption
} yield firstValue + secondValue
// myResult: Option[Int] = Some(3)

जब मूल्यों में से एक है, तो None गणना का अंतिम परिणाम None होगा।

val firstOption: Option[Int] = Option(1)
val secondOption: Option[Int] = None

val myResult = for {
  firstValue <- firstOption
  secondValue <- secondOption
} yield firstValue + secondValue
// myResult: Option[Int] = None

नोट: यह पैटर्न Monad s नामक अवधारणाओं के लिए अधिक सामान्यतः विस्तारित होता है। (अधिक जानकारी समझ और Monad लिए संबंधित पृष्ठों पर उपलब्ध होनी चाहिए)

सामान्य तौर पर समझ के लिए अलग-अलग मठों को मिश्रण करना संभव नहीं है। लेकिन चूंकि Option को आसानी से एक Iterable परिवर्तित किया जा सकता है, इसलिए हम .toIterable विधि को कॉल करके Option s और Iterable को आसानी से मिला सकते हैं।

val option: Option[Int] = Option(1)
val iterable: Iterable[Int] = Iterable(2, 3, 4, 5)

// does NOT compile since we cannot mix Monads in a for comprehension
// val myResult = for {
//   optionValue <- option
//   iterableValue <- iterable
//} yield optionValue + iterableValue

// It does compile when adding a .toIterable on the option
val myResult = for {
  optionValue <- option.toIterable
  iterableValue <- iterable
} yield optionValue + iterableValue
// myResult: Iterable[Int] = List(2, 3, 4, 5)

एक छोटा सा नोट: अगर हमने अपने दूसरे तरीके को समझने के लिए परिभाषित किया था, तो यह समझने के लिए कि हमारा विकल्प अनुमानित रूप से परिवर्तित हो जाएगा। इस कारण से यह हमेशा उपयोगी है। यह .toIterable (या किस फ़ंक्शन का उपयोग आप किस संग्रह के आधार पर कर रहे हैं) पर निर्भर करता है।



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow