वर्ग विकल्प [T] का क्या मतलब है?


83

मैं Option[T]स्काला में वर्ग की बात को समझने में सक्षम नहीं हूं । मेरा मतलब है, मैं किसी भी Noneओवर की सलाह को देखने में सक्षम नहीं हूं null

उदाहरण के लिए, कोड पर विचार करें:

object Main{
  class Person(name: String, var age: int){
    def display = println(name+" "+age)
  }

  def getPerson1: Person = {
    // returns a Person instance or null
  }

  def getPerson2: Option[Person] = {
    // returns either Some[Person] or None
  }

  def main(argv: Array[String]): Unit = {
    val p = getPerson1
    if (p!=null) p.display

    getPerson2 match{
      case Some(person) => person.display
      case None => /* Do nothing */
    }
  }
}

अब मान लें, विधि getPerson1वापस आती है null, तो displayपहली पंक्ति में की गई कॉल mainविफल होने के लिए बाध्य है NPE। इसी तरह अगर getPerson2रिटर्न मिलता है None, तो displayकॉल फिर से कुछ इसी तरह की त्रुटि के साथ विफल हो जाएगी।

यदि ऐसा है, तो स्काला Option[T]जावा में उपयोग किए जाने वाले सरल दृष्टिकोण का अनुसरण करने के बजाय नया वैल्यू रैपर ( ) शुरू करके चीजों को जटिल क्यों करता है ?

अपडेट करें:

मैंने अपना कोड @ मिच के सुझाव के अनुसार संपादित किया है । मैं अभी भी कोई विशेष लाभ नहीं देख पा रहा हूं Option[T]। मुझे असाधारण nullया Noneदोनों मामलों में परीक्षण करना होगा । :(

अगर मैंने @ माइकल के उत्तर से सही तरीके से समझा है , तो क्या इसका एकमात्र फायदा Option[T]यह है कि यह प्रोग्रामर को स्पष्ट रूप से बताता है कि यह तरीका कोई नहीं लौटा सकता है ? क्या इस डिजाइन की पसंद के पीछे यही एकमात्र कारण है?


23
वास्तव में, विकल्प [T] में "गेट" विधि का उच्चारण किया जाता है: "नर्क आप इसे मिलान क्यों नहीं कर रहे हैं?"
मिच बोलिंस

2
मिच सही है। उपयोग किए बिना अपने उदाहरण को पुनःप्रकाशित करने का प्रयास करें get, और आप इसे प्राप्त करेंगे। :-)
डैनियल सी। सोबरल

आपके पास पर्सन पी .. जो जावा है .. .टीरी वैल पी = ... इसके अलावा, डैनियल और साइनेसो द्वारा नीचे दिए गए विकल्प के रूप में अधिक है - यहां कुछ महान जवाब हैं।
माइकल निएले

@ मिचेल: उफ़! इशारा करने के लिए धन्यवाद; इसे ठीक किया।
लापताफैक्टर

जवाबों:


72

Optionयदि आप अपने आप को कभी भी, कभी भी उपयोग करने के लिए मजबूर करते हैं तो आपको बेहतर बात मिलेगी get। ऐसा इसलिए getहै क्योंकि "ओके के बराबर है, मुझे वापस अशक्त करने के लिए भेजें"।

तो, आपका वह उदाहरण लेते हैं। आप displayबिना उपयोग के कैसे कॉल करेंगे get? यहाँ कुछ विकल्प दिए गए हैं:

getPerson2 foreach (_.display)
for (person <- getPerson2) person.display
getPerson2 match {
  case Some(person) => person.display
  case _ =>
}
getPerson2.getOrElse(Person("Unknown", 0)).display

इस विकल्प में से कोई भी आपको displayउस चीज़ पर कॉल नहीं करने देगा जो मौजूद नहीं है।

क्यों getमौजूद है, इसके लिए स्काला आपको नहीं बताता कि आपका कोड कैसे लिखा जाना चाहिए। यह आपको धीरे से प्रभावित कर सकता है, लेकिन यदि आप बिना सुरक्षा जाल के वापस जाना चाहते हैं, तो यह आपकी पसंद है।


आपने इसे यहां लिया है:

विकल्प [T] का एकमात्र लाभ यह है कि यह प्रोग्रामर को स्पष्ट रूप से बताता है कि यह विधि कोई भी नहीं लौटा सकता है?

"केवल" को छोड़कर। लेकिन मुझे एक और तरीके से आराम करने दो: ओवर का मुख्य लाभ प्रकार की सुरक्षा है। यह सुनिश्चित करता है कि आप किसी ऐसी वस्तु को एक विधि नहीं भेज रहे हैं जो मौजूद नहीं हो सकती है, क्योंकि संकलक आपको नहीं जाने देगा।Option[T]TT

आपने कहा कि आपको दोनों मामलों में अशक्तता के लिए परीक्षण करना है, लेकिन अगर आप भूल जाते हैं - या नहीं जानते - आपको अशक्त के लिए जांचना होगा, तो संकलक आपको बताएगा? या आपके उपयोगकर्ता?

बेशक, जावा के साथ अपनी अंतर्संचालनीयता के कारण, स्काला केवल नल को ही अनुमति देता है, जैसा कि जावा करता है। इसलिए यदि आप जावा पुस्तकालयों का उपयोग करते हैं, यदि आप बुरी तरह से लिखित स्काला पुस्तकालयों का उपयोग करते हैं, या यदि आप बुरी तरह से लिखित व्यक्तिगत पुस्तकालयों का उपयोग करते हैं , तो आपको अभी भी अशक्त बिंदुओं से निपटना होगा।

Optionमैं सोच सकता हूँ के अन्य दो महत्वपूर्ण लाभ हैं:

  • प्रलेखन: एक विधि प्रकार का हस्ताक्षर आपको बताएगा कि क्या कोई वस्तु हमेशा लौटा दी जाती है या नहीं।

  • मोनैडिक रचना।

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

for {
  person <- getUsers
  email <- person.getEmail // Assuming getEmail returns Option[String]
} yield (person, email)

5
"अपने आप को कभी भी, कभी भी उपयोग करने के लिए मजबूर करें get" -> तो, दूसरे शब्दों में: "आप ऐसा नहीं getकरते हैं!" :)
fredoverflow

31

की तुलना करें:

val p = getPerson1 // a potentially null Person
val favouriteColour = if (p == null) p.favouriteColour else null

साथ में:

val p = getPerson2 // an Option[Person]
val favouriteColour = p.map(_.favouriteColour)

मानदिक संपत्ति बाइंड , जो स्काला में मानचित्र फ़ंक्शन के रूप में दिखाई देती है, हमें वस्तुओं पर चेन संचालन की अनुमति देती है, बिना इस बात की परवाह किए कि वे 'अशक्त' हैं या नहीं।

इस सरल उदाहरण को थोड़ा और आगे ले जाएं। कहें कि हम लोगों की सूची के सभी पसंदीदा रंग ढूंढना चाहते थे।

// list of (potentially null) Persons
for (person <- listOfPeople) yield if (person == null) null else person.favouriteColour

// list of Options[Person]
listOfPeople.map(_.map(_.favouriteColour))
listOfPeople.flatMap(_.map(_.favouriteColour)) // discards all None's

या शायद हम किसी व्यक्ति के पिता की माँ की बहन का नाम खोजना चाहेंगे:

// with potential nulls
val father = if (person == null) null else person.father
val mother = if (father == null) null else father.mother
val sister = if (mother == null) null else mother.sister

// with options
val fathersMothersSister = getPerson2.flatMap(_.father).flatMap(_.mother).flatMap(_.sister)

मुझे आशा है कि यह इस बात पर कुछ प्रकाश डालेगा कि कैसे विकल्प जीवन को थोड़ा आसान बना सकते हैं।


आपके अंतिम उदाहरण में यदि व्यक्ति का पिता अशक्त है तो क्या होगा? mapवापस आएगा Noneऔर कॉल कुछ त्रुटि के साथ विफल हो जाएगा। यह nullदृष्टिकोण से बेहतर कैसे है ?
लापताफैक्टर

5
नहीं। यदि व्यक्ति कोई नहीं है (या पिता, माता या बहन), तो पितामह भीमिनी कोई नहीं होगी, लेकिन कोई त्रुटि नहीं होगी।
प्रतिमान

6
मुझे लगता है कि आप नक्शे के बजाय सपाट नक्शा मतलब है।
रेट्रो

डैनियल एडिट के लिए धन्यवाद। मैंने इसे पोस्ट करने से पहले कोड की कोशिश नहीं की। अगली बार बेहतर करेंगे।
सायेंसो

2
Val favouriteColour = if (p == null) p.favouriteColour अन्यथा null // ठीक है कि विकल्प आपको बचने में मदद करता है! इस जवाब के वर्षों के लिए यहाँ है किसी को भी इस त्रुटि जगह के बिना!
मार्क लिस्टर

22

अंतर सूक्ष्म है। सही मायने में एक फ़ंक्शन होने का ध्यान रखें कि इसे एक मूल्य वापस करना चाहिए - नल को वास्तव में "सामान्य वापसी मूल्य" नहीं माना जाता है, इस अर्थ में, एक निचला प्रकार / कुछ भी नहीं।

लेकिन, एक व्यावहारिक अर्थ में, जब आप किसी ऐसे फ़ंक्शन को कहते हैं जो वैकल्पिक रूप से कुछ देता है, तो आप ऐसा करेंगे:

getPerson2 match {
   case Some(person) => //handle a person
   case None => //handle nothing 
}

दी, आप अशक्त के साथ कुछ ऐसा ही कर सकते हैं - लेकिन यह इस getPerson2तथ्य के आधार पर स्पष्ट रूप से कॉल करने का शब्दार्थ बनाता है Option[Person]( यह एक अच्छी व्यावहारिक बात है, डॉक्टर को पढ़ने वाले किसी व्यक्ति पर भरोसा करने और एनपीई प्राप्त करने के अलावा, क्योंकि वे पढ़ते नहीं हैं doc)।

मैं कोशिश करूंगा और एक कार्यात्मक प्रोग्रामर को खोद सकता हूं, जो मुझे जितना संभव हो उतना सख्त जवाब दे सकता है।


1
विकल्प के बारे में भी मेरी यही समझ है। यह प्रोग्रामर को स्पष्ट रूप से बताता है कि हमें कोई नहीं मिल सकता है, और यदि आप कुछ (टी) करने के लिए याद रखने के लिए पर्याप्त मूर्ख हैं, लेकिन कोई नहीं पकड़ता है और साथ ही साथ आप मुसीबत में हैं।
cflewis

1
लेविशम - मुझे लगता है कि कंपाइलर आपको एक चेतावनी देगा क्योंकि कुछ / कोई नहीं एक बीजीय डेटा प्रकार (अमूर्त सीलबंद विशेषता ...) बनाता है (लेकिन मैं यहां मेमोरी से जा रहा हूं)।
माइकल नीले

6
अधिकांश भाषाओं में विकल्प प्रकार का उपयोग करने वाली बात यह है कि रनटाइम अशक्त अपवाद के बजाय आपको एक संकलन समय त्रुटि मिलती है - संकलनकर्ता यह जान सकता है कि आपके पास डेटा का उपयोग करते समय कोई भी स्थिति के लिए कोई कार्रवाई नहीं है, जिसे करना चाहिए एक प्रकार की त्रुटि हो।
जस्टिन स्मिथ

15

मेरे लिए विकल्प वास्तव में दिलचस्प हैं जब समझ वाक्य रचना के लिए संभाला जाता है। ले रहा है synesso पूर्ववर्ती उदाहरण:

// with potential nulls
val father = if (person == null) null else person.father
val mother = if (father == null) null else father.mother
val sister = if (mother == null) null else mother.sister

// with options
val fathersMothersSister = for {
                                  father <- person.father
                                  mother <- father.mother
                                  sister <- mother.sister
                               } yield sister

यदि कोई असाइनमेंट है None, तो fathersMothersSisterहोगा , Noneलेकिन NullPointerExceptionउठाया नहीं जाएगा। फिर आप fathersMothersSisterचिंता किए बिना विकल्प मापदंडों को लेते हुए सुरक्षित रूप से एक समारोह में जा सकते हैं। इसलिए आप अशक्त के लिए जाँच नहीं करते हैं और आप अपवादों की परवाह नहीं करते हैं। इसकी तुलना synesso उदाहरण में प्रस्तुत जावा संस्करण से करें ।


3
यह शर्म की बात है कि स्काला में <-सिंटैक्स "लिस्ट कॉम्प्रिहेंशन सिंटैक्स" तक ही सीमित है, क्योंकि यह वास्तव में doहास्केल से अधिक सामान्य सिंटैक्स या domonadक्लोजर के मोनड लाइब्रेरी से फॉर्म के समान है। इसे सूचियों में बांधना इसे कम बेचता है।
सेह

11
स्काला में "समझ के लिए" अनिवार्य रूप से हास्केल में "करते" हैं, वे सूचियों तक सीमित नहीं हैं, आप कुछ भी उपयोग कर सकते हैं जो लागू होते हैं: डिफ मैप [बी] (एफ: ए => बी): सी [बी] डीफ फ्लैटपॉप [बी] (एफ: ए => सी [बी]): सी [बी] डीफ फिल्टर (पी: ए => बुलियन): सी [ए]। IOW, कोई भी
मोनाड

2
@seh मैंने @ GClaramunt की टिप्पणी को गलत ठहराया, लेकिन मैं उनकी बात पर जोर नहीं दे सकता। नहीं है कोई पूर्व के साथ बाद किया जा रहा है प्रयोग करने योग्य के लिए छोड़कर - स्काला में लिए-comprehensions और सूचियों के बीच संबंध। मैं आपको stackoverflow.com/questions/1052476/… का संदर्भ देता हूं ।
डैनियल सी। सोबरल

हां, मुझे पता है कि कोई संबंध नहीं है, लेकिन मैं मानता हूं कि यह इंगित करने लायक है; मैं इस उत्तर की पहली पंक्ति पर टिप्पणी कर रहा था, जहाँ विरोधाभासी उल्लेख है "सूची बोध वाक्यविन्यास"। यह भाषा की समस्या के विपरीत एक शिक्षण समस्या है।
सेह

9

आपके पास विकल्प के साथ बहुत शक्तिशाली संरचना क्षमताएं हैं:

def getURL : Option[URL]
def getDefaultURL : Option[URL]


val (host,port) = (getURL orElse getDefaultURL).map( url => (url.getHost,url.getPort) ).getOrElse( throw new IllegalStateException("No URL defined") )

क्या आप इसे पूरी तरह से समझा सकते हैं?
जेस्विन जोस

8

हो सकता है कि किसी और ने इसे इंगित किया हो, लेकिन मैंने इसे नहीं देखा:

विकल्प [टी] बनाम शून्य जाँच के साथ पैटर्न-मिलान का एक फायदा यह है कि विकल्प एक सील वर्ग है, इसलिए स्केल कंपाइलर एक चेतावनी जारी करेगा यदि आप या तो कुछ या किसी भी मामले को कोड करने के लिए उपेक्षा करते हैं। कंपाइलर के लिए एक कंपाइलर फ्लैग होता है जो चेतावनी को त्रुटियों में बदल देगा। इसलिए रनटाइम के बजाय संकलन समय पर "अस्तित्व में नहीं है" मामले को संभालने में विफलता को रोकना संभव है। यह शून्य मान के उपयोग पर भारी लाभ है।


7

यह एक अशक्त जांच से बचने में मदद करने के लिए नहीं है, यह एक अशक्त जांच को मजबूर करने के लिए है। बिंदु स्पष्ट हो जाता है जब आपकी कक्षा में 10 क्षेत्र होते हैं, जिनमें से दो शून्य हो सकते हैं। और आपके सिस्टम में 50 अन्य समान कक्षाएं हैं। जावा दुनिया में, आप उन क्षेत्रों पर एनपीई को रोकने की कोशिश करते हैं, जो मानसिक हॉर्सपावर, नामकरण सम्मेलन, या शायद एनोटेशन के कुछ संयोजन का उपयोग करते हैं। और हर जावा देव इस पर एक महत्वपूर्ण डिग्री तक विफल रहता है। विकल्प वर्ग न केवल "अशक्त" मूल्यों को स्पष्ट रूप से किसी भी डेवलपर्स को समझने की कोशिश करता है जो कोड को समझने की कोशिश कर रहा है, बल्कि संकलक को इस पहले से अनिच्छुक अनुबंध को लागू करने की अनुमति देता है।


6

[ डैनियल Spiewak द्वारा इस टिप्पणी की प्रतिलिपि बनाई गई ]

यदि उपयोग करने का एकमात्र तरीका Optionमानों को बाहर निकालने के लिए मैच को पैटर्न करना था, तो हाँ, मैं मानता हूं कि यह सभी अशक्त में सुधार नहीं करता है। हालाँकि, आपको इसकी कार्यक्षमता का एक * विशाल * वर्ग याद आ रहा है। उपयोग करने के लिए केवल सम्मोहक कारण यह Optionहै कि आप अपने उच्च-क्रम उपयोगिता कार्यों का उपयोग कर रहे हैं। प्रभावी रूप से, आपको इसकी विवादास्पद प्रकृति का उपयोग करने की आवश्यकता है। उदाहरण के लिए (एपीआई ट्रिमिंग की एक निश्चित राशि मानकर):

val row: Option[Row] = database fetchRowById 42
val key: Option[String] = row flatMap { _ get “port_key” }
val value: Option[MyType] = key flatMap (myMap get)
val result: MyType = value getOrElse defaultValue

वहाँ, कि निफ्टी नहीं था? हम वास्तव में एक बहुत अच्छा कर सकते हैं अगर हम for-प्रयोग का उपयोग करें:

val value = for {
row <- database fetchRowById 42
key <- row get "port_key"
value <- myMap get key
} yield value
val result = value getOrElse defaultValue

आप देखेंगे कि हम * कभी नहीं * स्पष्ट रूप से अशक्त, कोई भी या इसके ilk के लिए जाँच कर रहे हैं। विकल्प का पूरा बिंदु उस जाँच से किसी भी तरह से बचना है। आप बस स्ट्रिंग संगणना करते हैं और जब तक आप वास्तव में * एक मूल्य प्राप्त करने की आवश्यकता होती है, तब तक लाइन को नीचे नहीं ले जाते हैं। उस बिंदु पर, आप यह तय कर सकते हैं कि आप स्पष्ट जाँच करना चाहते हैं या नहीं (जो आपको कभी नहीं करना चाहिए ), एक डिफ़ॉल्ट मान प्रदान करें, एक अपवाद फेंकें, आदि।

मैं कभी भी, कभी कोई स्पष्ट मिलान नहीं करता Optionहूं, और मैं बहुत से अन्य स्कैल डेवलपर्स को जानता हूं जो एक ही नाव में हैं। डेविड पोलाक ने मुझे दूसरे दिन ही उल्लेख किया कि वह इस तरह के स्पष्ट मिलान का उपयोग करता है Option(या Box, लिफ्ट के मामले में) एक संकेत के रूप में कि कोड लिखने वाले डेवलपर भाषा और उसके मानक पुस्तकालय को पूरी तरह से नहीं समझते हैं।

मेरा मतलब ट्रोल हथौड़ा नहीं है, लेकिन आपको वास्तव में यह देखने की ज़रूरत है कि भाषा की विशेषताएं * वास्तव में * व्यवहार में कैसे उपयोग की जाती हैं, इससे पहले कि आप उन्हें बेकार समझें। मैं इस बात से पूरी तरह सहमत हूँ कि विकल्प * के रूप में काफी अनिश्चित है * आपने इसका उपयोग किया है, लेकिन आप इसे उस तरह से उपयोग नहीं कर रहे हैं जैसे इसे डिज़ाइन किया गया था।


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

4
मुझे लगता है कि आप स्काला की समझ को गलत समझ रहे हैं। दूसरा उदाहरण जोरदार नहीं है एक लूप है, इसे संकलक द्वारा फ्लैटपाइप संचालन की एक श्रृंखला में अनुवादित किया गया है - पहले उदाहरण के अनुसार।
केविन राइट

मुझे अपनी टिप्पणी लिखे यहाँ एक लंबा समय हो गया है, लेकिन मैंने केविन को देखा। केविन, जब आप "आप गलतफहमी" लिखा था, जिसका आप उल्लेख कर रहे थे? मैं नहीं दिख रहा है कि यह कैसे हो सकता था मुझे , जैसा कि मैंने एक पाश बारे में कुछ भी उल्लेख नहीं।
सेह

6

एक बिंदु जो यहां किसी और को नहीं लगता है, वह यह है कि जब आपके पास एक शून्य संदर्भ हो सकता है, तो विकल्प द्वारा पेश किया गया एक अंतर है।

यही कारण है कि आप हो सकते हैं Option[Option[A]], जो कि निवास करेगा None, Some(None)और Some(Some(a))जहां aके सामान्य निवासियों में से एक है A। इसका मतलब है कि यदि आपके पास कुछ प्रकार के कंटेनर हैं, और इसमें अशक्त बिंदुओं को संग्रहीत करने में सक्षम होना चाहते हैं, और उन्हें बाहर निकालना चाहते हैं, तो आपको यह जानने के लिए कुछ अतिरिक्त बूलियन मान वापस पास करने की आवश्यकता है कि क्या आपको वास्तव में एक मूल्य मिला है। इस तरह मौसा लाजिमी जावा कंटेनर APIs में और कुछ ताला मुक्त वेरिएंट यहां तक कि उन्हें प्रदान नहीं कर सकते।

null एक निर्माण बंद है, यह खुद के साथ रचना नहीं करता है, यह केवल संदर्भ प्रकारों के लिए उपलब्ध है, और यह आपको गैर-कुल फैशन में तर्क करने के लिए मजबूर करता है।

उदाहरण के लिए, जब आप जांच करते हैं

if (x == null) ...
else x.foo()

आपको पूरी elseशाखा में अपने सिर के चारों ओर ले जाना होगा x != nullऔर यह पहले से ही जांचा जा चुका है। हालांकि, विकल्प जैसे कुछ का उपयोग करते समय

x match {
case None => ...
case Some(y) => y.foo
}

आपको पता है कि y Noneनिर्माण से नहीं है - और आपको पता होगा कि यह nullया तो नहीं था , अगर यह होरे की अरब डॉलर की गलती के लिए नहीं थे ।


3

विकल्प [टी] एक सन्यासी है, जो मूल्यों में हेरफेर करने के लिए उच्च-क्रम के कार्यों का उपयोग करते समय वास्तव में उपयोगी होता है।

मैं आपको नीचे सूचीबद्ध लेख पढ़ने का सुझाव दूंगा, वे वास्तव में अच्छे लेख हैं जो आपको दिखाते हैं कि विकल्प [टी] क्यों उपयोगी है और इसे कार्यात्मक तरीके से कैसे उपयोग किया जा सकता है।


मैं अनुशंसित पठन सूची टोनी मॉरिस की हाल ही में प्रकाशित ट्यूटोरियल "व्हाट डू मोनड मीन?": प्रोजेक्ट्स
रान्डेल शुल्ज

3

एक जवाब के रान्डेल के टीज़र पर जोड़ना , यह समझना कि मूल्य की संभावित अनुपस्थिति का प्रतिनिधित्व क्यों किया जाता है, यह समझने की Optionआवश्यकता है कि Optionस्काला में कई अन्य प्रकारों के साथ क्या-क्या शेयर हैं, विशेष रूप से, प्रकार के साधु। यदि कोई अशक्त के साथ एक मूल्य की अनुपस्थिति का प्रतिनिधित्व करता है, तो अनुपस्थिति-उपस्थिति का अंतर अन्य राक्षसी प्रकारों द्वारा साझा किए गए अनुबंधों में भाग नहीं ले सकता है।

यदि आप नहीं जानते कि भिक्षु क्या हैं, या यदि आप यह नहीं देखते हैं कि वे कैसे स्काला की लाइब्रेरी में प्रतिनिधित्व करते हैं, तो आप यह नहीं देखेंगे कि आपके Optionसाथ क्या खेलते हैं, और आप यह नहीं देख सकते हैं कि आप क्या याद कर रहे हैं। का उपयोग करने के कई फायदे होते हैं Optionअशक्त कि उल्लेखनीय भी किसी भी इकाई अवधारणा के अभाव में किया जाएगा के बजाय (मैं "विकल्प की लागत / अशक्त बनाम कुछ" में उनमें से कुछ के बारे में बात स्केला-उपयोगकर्ता मेलिंग सूची धागा यहाँ ), लेकिन के बारे में बात यह अलगाव एक विशेष रूप से जुड़े हुए सूची कार्यान्वयन के इट्रेटर प्रकार के बारे में बात करने की तरह है, यह सोचकर कि यह क्यों आवश्यक है, जबकि सभी अधिक सामान्य कंटेनर / पुनरावृत्ति / एल्गोरिथ्म इंटरफ़ेस से गायब है। यहाँ काम पर एक व्यापक इंटरफ़ेस भी है,Option


लिंक के लिए बहुत बहुत धन्यवाद। यह वास्तव में उपयोगी था। :)
लापताफैक्टर

धागे पर आपकी टिप्पणी इतनी संक्षिप्त थी कि मैं लगभग अपनी बात कहने से चूक गया। मैं वास्तव में चाहता हूं कि अशक्त पर प्रतिबंध लगाया जा सके।
Alain O'Dea

2

मुझे लगता है कि कुंजी सिनेसियो के उत्तर में पाई गई है: विकल्प मुख्य रूप से अशक्त के लिए बोझिल उर्फ ​​के रूप में उपयोगी नहीं है , लेकिन एक पूर्ण वस्तु के रूप में जो तब आपके तर्क के साथ आपकी मदद कर सकती है।

अशक्त के साथ समस्या यह है कि यह एक वस्तु की कमी है। इसकी कोई विधि नहीं है जो आपको इससे निपटने में मदद कर सकती है (हालांकि एक भाषा डिजाइनर के रूप में आप अपनी भाषा में सुविधाओं की तेजी से लंबी सूची जोड़ सकते हैं जो एक वस्तु का अनुकरण करते हैं यदि आप वास्तव में ऐसा महसूस करते हैं)।

एक चीज़ विकल्प, जैसा कि आपने प्रदर्शित किया है, अशक्त करना है; फिर आपको असाधारण मूल्य "अशक्त" के बजाय असाधारण मूल्य "कोई नहीं" के लिए परीक्षण करना होगा। यदि आप भूल जाते हैं, तो किसी भी स्थिति में, खराब चीजें होंगी। विकल्प से दुर्घटना होने की संभावना कम हो जाती है, क्योंकि आपको "गेट" टाइप करना है (जो आपको याद दिलाना चाहिए कि यह अशक्त हो सकता है , एर, मेरा मतलब कोई नहीं है), लेकिन अतिरिक्त आवरण वस्तु के बदले में यह एक छोटा लाभ है ।

जहां विकल्प वास्तव में अपनी शक्ति दिखाना शुरू कर देता है, आपको I-वांटेड-समथिंग-बट-आई-नॉट-वास्तव में एक-एक की अवधारणा से निपटने में मदद कर रहा है।

आइए कुछ बातों पर विचार करें जो आप उन चीजों के साथ करना चाहते हैं जो अशक्त हो सकती हैं।

यदि आप अशक्त हैं तो शायद आप एक डिफ़ॉल्ट मान सेट करना चाहते हैं। जावा और स्काला की तुलना करें:

String s = (input==null) ? "(undefined)" : input;
val s = input getOrElse "(undefined)"

कुछ बोझिल होने के स्थान पर ?: निर्माण हमारे पास एक विधि है जो "अगर मैं अशक्त हूं तो एक डिफ़ॉल्ट मूल्य का उपयोग करने" के विचार से संबंधित है। इससे आपका कोड थोड़ा साफ हो जाता है।

हो सकता है कि आप एक नया ऑब्जेक्ट तभी बनाना चाहते हैं जब आपके पास वास्तविक मूल्य हो। की तुलना करें:

File f = (filename==null) ? null : new File(filename);
val f = filename map (new File(_))

स्काला थोड़ा छोटा है और फिर से त्रुटि के स्रोतों से बचा जाता है। तब संचयी लाभ पर विचार करें जब आपको चीजों को एक साथ श्रृंखलाबद्ध करने की आवश्यकता होती है जैसा कि साइनेसियो, डैनियल और प्रतिमान द्वारा उदाहरणों में दिखाया गया है।

यह एक बहुत बड़ा सुधार नहीं है , लेकिन अगर आप सब कुछ जोड़ते हैं, तो यह बहुत ही अच्छी तरह से इसके लायक है हर जगह बहुत उच्च-प्रदर्शन कोड (जहां आप कुछ (x) आवरण ऑब्जेक्ट बनाने के छोटे ओवरहेड से बचना चाहते हैं) को बचा सकते हैं।

मैच का उपयोग वास्तव में ऐसा नहीं है, जो अपने आप में एक उपकरण के रूप में आपको अशक्त / किसी भी मामले के बारे में सतर्क करने के लिए छोड़कर उपयोगी नहीं है। जब यह वास्तव में मददगार होता है जब आप इसका पीछा करना शुरू करते हैं, उदाहरण के लिए, यदि आपके पास विकल्पों की सूची है:

val a = List(Some("Hi"),None,Some("Bye"));
a match {
  case List(Some(x),_*) => println("We started with " + x)
  case _ => println("Nothing to start with.")
}

अब आप किसी भी मामले को सूचीबद्ध नहीं कर सकते हैं और लिस्ट-ए-खाली मामलों को सभी एक साथ एक आसान बयान में डालते हैं जो आपके इच्छित मान को खींचता है।


2

नल वापसी मान केवल जावा के साथ संगतता के लिए मौजूद हैं। आपको उनका उपयोग अन्यथा नहीं करना चाहिए।


1

यह वास्तव में एक प्रोग्रामिंग स्टाइल प्रश्न है। फ़ंक्शनल जावा का उपयोग करना, या अपने स्वयं के सहायक तरीकों को लिखकर, आप अपनी ऑप्शनल फ़ंक्शनलिटी रख सकते हैं, लेकिन जावा लैंग्वेज को न छोड़ें:

http://functionaljava.org/examples/#Option.bind

सिर्फ इसलिए कि स्काला इसे डिफ़ॉल्ट रूप से शामिल करता है, इसे विशेष नहीं बनाता है। उस पुस्तकालय में कार्यात्मक भाषाओं के अधिकांश पहलू उपलब्ध हैं और यह अन्य जावा कोड के साथ अच्छी तरह से जुड़ सकता है। जैसे आप nalas के साथ Scala प्रोग्राम करना चुन सकते हैं, वैसे ही आप उनके बिना Java प्रोग्राम कर सकते हैं।


0

पहले से स्वीकार करते हुए कि यह एक शानदार जवाब है, विकल्प एक सनक है।


मुझे पता है कि यह एक सन्यासी है। मैं प्रश्न में "मोनड" टैग क्यों शामिल करूंगा?
लापताफैक्टर

^ उपरोक्त कथन का मतलब यह नहीं है कि मैं समझता हूं कि एक सन्यासी क्या है। : डी
गुमशुदा

4
मठरी ठंडी होती है। यदि आप उनका उपयोग नहीं करते हैं या कम से कम समझने का दिखावा नहीं करते हैं, तो आप शांत नहीं हैं ;-)
प्रतिमान

0

वास्तव में मैं आपके साथ संदेह साझा करता हूं। विकल्प के बारे में यह वास्तव में मुझे परेशान करता है कि 1) एक प्रदर्शन ओवरहेड है, क्योंकि "कुछ" रैपर का एक लवर है, जो हर चीज का निर्माण करता है। 2) मुझे अपने कोड में बहुत कुछ और विकल्प का उपयोग करना है।

इस भाषा के डिजाइन निर्णय के फायदे और नुकसान को देखने के लिए हमें विकल्पों पर विचार करना चाहिए। जैसा कि जावा सिर्फ अशक्तता की समस्या को नजरअंदाज करता है, यह एक विकल्प नहीं है। वास्तविक विकल्प फैंटम प्रोग्रामिंग भाषा प्रदान करता है। वहाँ अशक्त और गैर-अशक्त प्रकार हैं और? ?: स्काला के नक्शे / फ्लैटपाइप / getOrElse के बजाय ऑपरेटर। मैं तुलना में निम्नलिखित गोलियों को देखता हूं:

विकल्प का लाभ:

  1. सरल भाषा - कोई अतिरिक्त भाषा निर्माण की आवश्यकता नहीं है
  2. अन्य विवादास्पद प्रकारों के साथ वर्दी

अशक्त का लाभ:

  1. ठेठ मामलों में कम वाक्य रचना
  2. बेहतर प्रदर्शन (जैसा कि आपको नए विकल्प ऑब्जेक्ट और मैप के लिए लैम्ब्डा बनाने की आवश्यकता नहीं है, फ्लैट मैप)

इसलिए यहां कोई स्पष्ट विजेता नहीं है। और एक और नोट। विकल्प का उपयोग करने के लिए कोई मूल वाक्यविन्यास लाभ नहीं है। आप कुछ इस तरह परिभाषित कर सकते हैं:

def nullableMap[T](value: T, f: T => T) = if (value == null) null else f(value)

या डॉट्स के साथ प्रीटी सिंटैक्स प्राप्त करने के लिए कुछ निहित रूपांतरणों का उपयोग करें।


क्या किसी ने आधुनिक वीएम पर हिट प्रदर्शन पर ठोस बेंचमार्क किया है? पलायन विश्लेषण का मतलब है कि ढेर पर कई अस्थायी विकल्प वस्तुओं को आवंटित किया जा सकता है (ढेर की तुलना में सस्ता), और पीढ़ीगत जीसी बहुत कम अस्थायी वस्तुओं को बहुत कुशलता से संभालती है। बेशक अगर NPEs से बचने की तुलना में गति आपके प्रोजेक्ट के लिए अधिक महत्वपूर्ण है, तो विकल्प शायद आपके लिए नहीं हैं।
जस्टिन डब्ल्यू

इसे वापस करने के लिए संख्या के बिना प्रदर्शन ओवरहेड का उल्लेख न करें। यह विकल्प की तरह अमूर्त के खिलाफ बहस करते समय एक अत्यंत सामान्य गलती है। यदि आप कोई संकेत देते हैं या कोई प्रदर्शन प्रकाशित करते हैं या प्रदर्शन टिप्पणी हटाते हैं, तो मैं ख़ुशी-ख़ुशी अपना परित्याग कर दूंगा या प्रदर्शन टिप्पणी हटा दूंगा :)
Alain O'Dea

0

स्पष्ट विकल्प प्रकार होने का वास्तविक लाभ यह है कि आप उन्हें 98% सभी स्थानों पर उपयोग करने में सक्षम नहीं हैं, और इस तरह से सांख्यिकीय रूप से शून्य अपवाद हैं। (और अन्य 2% में टाइप सिस्टम आपको ठीक से जांचने के लिए याद दिलाता है जब आप वास्तव में उन तक पहुंचते हैं।)


-3

एक अन्य स्थिति जहां विकल्प काम करता है, ऐसी स्थितियों में जहां प्रकार एक अशक्त मूल्य के लिए सक्षम नहीं हैं। नल को इंट, फ्लोट, डबल, आदि मूल्य में संग्रहीत करना संभव नहीं है, लेकिन एक विकल्प के साथ आप कोई भी उपयोग नहीं कर सकते हैं।

जावा में, आपको उन प्रकारों के बॉक्स वाले संस्करणों (पूर्णांक, ...) का उपयोग करने की आवश्यकता होगी।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.