Scala Language
विकल्प वर्ग
खोज…
वाक्य - विन्यास
वर्ग कुछ [+ 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
(या किस फ़ंक्शन का उपयोग आप किस संग्रह के आधार पर कर रहे हैं) पर निर्भर करता है।