2011-06-20 11 views
31

ग्रूवी भाषा में, यह null या false तरह की जांच के लिए बहुत सरल है:स्कैला में संक्षेप में शून्य या झूठी जांच कैसे करें?

ग्रूवी कोड:

def some = getSomething() 
if(some) { 
// do something with some as it is not null or emtpy 

} 

ग्रूवी में अगर somenull है या खाली स्ट्रिंग या शून्य नंबर आदि का मूल्यांकन करेंगे false पर। स्केल में null या false के लिए परीक्षण की समान संक्षिप्त विधि क्या है? some मानते हुए प्रश्न के इस हिस्से का सरल जवाब जावा प्रकार स्ट्रिंग का बस है?

इसके अलावा ग्रूवी में एक और भी बेहतर तरीका है:

def str = some?.toString() 

जिसका अर्थ है यदि somenull तो some पर toString विधि के बजाय मामले some में एनपीई फेंकने की लागू किया जाएगा नहीं है null था। स्कला में समान क्या है?

+0

IMO, डैनियल का जवाब नीचे सबसे उपयुक्त है। स्कैला के पास संभावित रूप से खाली मूल्यों से निपटने के लिए पहले से ही बहुत सारे समर्थन हैं - सीखने के लिए बेहतर है और इसका उपयोग नए '?' वाक्यविन्यास को implicits के साथ बनाने के लिए किया जाता है। – Bill

+1

एक कारण यह 'बजाय null's साथ जाने के लिए' None's प्रदर्शन/स्मृति उपयोग हो सकता है - आप मक्खी पर निहित रूपांतरण से एक अल्पकालिक वस्तु आवंटन के बजाय एक 'Option' आवरण के आसपास रखने पसंद कर सकते हैं। अनुमोदित, बहुत से लोग JVM पर उच्च-प्रदर्शन कोड नहीं लिखते हैं, लेकिन फिर भी, मैं कहूंगा कि इसका उपयोग-मामलों में है। – axel22

उत्तर

49

आप क्या खो सकते हैं यह है कि स्कैला में getSomething जैसे फ़ंक्शन शायद शून्य, खाली स्ट्रिंग या शून्य नंबर वापस नहीं आएगा। एक ऐसा फ़ंक्शन जो एक सार्थक मूल्य लौटा सकता है या हो सकता है कि वह Option पर वापस न आए - यह Some(meaningfulvalue) या None लौटाएगा।

तो आप इस के लिए जाँच करें और वापसी मान में "विफलता" मूल्य सांकेतिक शब्दों में बदलना करने की कोशिश कर के बजाय

val some = getSomething() 
some match { 
    case Some(theValue) => doSomethingWith(theValue) 
    case None   => println("Whoops, didn't get anything useful back") 
} 

की तरह कुछ के साथ सार्थक मूल्य संभाल कर सकते हैं, स्काला आम "वापसी के लिए विशिष्ट समर्थन हासिल है कुछ सार्थक या विफलता संकेत "मामला।

ऐसा कहकर, स्कैला जावा के साथ अंतःक्रियाशील है, और जावा हर समय कार्यों से नल लौटाता है। यदि getSomething एक जावा फ़ंक्शन है जो शून्य देता है, तो एक फैक्ट्री ऑब्जेक्ट होता है जो कुछ या कोई भी लौटाए गए मूल्य से बाहर नहीं करेगा।

तो

val some = Option(getSomething()) 
    some match { 
    case Some(theValue) => doSomethingWith(theValue) 
    case None   => println("Whoops, didn't get anything useful back") 
    } 

... जो बहुत सरल है, मैं दावा है, और आप पर एनपीई नहीं जाएगी।

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

+0

धन्यवाद! मैं आपके समाधान का उपयोग कर समाप्त हुआ लेकिन खेद है कि मैंने समाधान के रूप में पहले से ही एक और जवाब चिह्नित किया था। – ace

+1

यह मेरी सबसे खराब स्केल सुविधा है जो मैंने अपने एक महीने की यात्रा में अब तक का सामना किया है .. यह स्कैला की "टाइप कम" विचारधारा के लिए क्षमा है। आईएमओ एनपीई को ठीक करना आसान है और आप अपने लिए सब कुछ करने के लिए लैंग पर भरोसा नहीं कर सकते हैं। यहां तक ​​कि विकल्प के साथ लोग कोड लिख सकते हैं जो एनपीई की ओर ले जाएगा। यानी अगर मैच के मामले में अगर कोई सिर्फ कुछ (वैल) .get तो करता है तो आपको अभी भी एनपीई मिलती है। शायद लाइन के नीचे यह अधिक उपयोगी लग सकता है लेकिन अब तक मुझे किसी भी लेख का सामना करना पड़ता है जो अन्यथा बताता है – nir

+0

चलते रहें, और मैं भविष्यवाणी करता हूं कि आप अपना दिमाग बदल देंगे। बेशक आप कोशिश करते हैं तो एनपीई को उत्तेजित कर सकते हैं, लेकिन स्कैला में अच्छी प्रैक्टिस विकल्प का उपयोग नहीं करना है .get - इसे करने के कई बेहतर तरीके हैं। –

19

स्कैला में, आपके द्वारा वर्णित अभिव्यक्ति का अर्थ है कि ? नामक एक विधि को some नामक ऑब्जेक्ट पर बुलाया जाता है। नियमित रूप से, वस्तुओं में ? नामक विधि नहीं होती है। आप ? विधि के साथ किसी ऑब्जेक्ट में अपना स्वयं का अंतर्निहित रूपांतरण बना सकते हैं जो null नेस के लिए जांच करता है।

implicit def conversion(x: AnyRef) = new { 
    def ? = x ne null 
} 

ऊपर होगा, संक्षेप में, किसी भी वस्तु जिस पर आप विधि conversion के दाहिने हाथ की ओर अभिव्यक्ति में विधि ? फोन (जो करता? विधि है) में परिवर्तित। उदाहरण के लिए, अगर आप इस:

"".? 

संकलक की पहचान करेगा एक String वस्तु नहीं ? विधि है, और में यह पुनर्लेखन: एक दुभाषिया में

conversion("").? 

इलस्ट्रेटेड (ध्यान रखें कि छोड़ सकते हैं . वस्तुओं पर जब फोन करने के तरीकों):

scala> implicit def any2hm(x: AnyRef) = new { 
    | def ? = x ne null 
    | } 
any2hm: (x: AnyRef)java.lang.Object{def ?: Boolean} 

scala> val x: String = "!!" 
x: String = "!!" 

scala> x ? 
res0: Boolean = true 

scala> val y: String = null 
y: String = null 

scala> y ? 
res1: Boolean = false 

तो तुम लिख सकते हैं:

if (some ?) { 
    // ... 
} 

या अगर तर्क null नहीं है आप एक ? विधि है जो वस्तु पर निर्दिष्ट विधि आह्वान के साथ एक वस्तु में एक अंतर्निहित रूपांतरण बना सकते हैं - ऐसा:

scala> implicit def any2hm[T <: AnyRef](x: T) = new { 
    | def ?(f: T => Unit) = if (x ne null) f(x) 
    | } 
any2hm: [T <: AnyRef](x: T)java.lang.Object{def ?(f: (T) => Unit): Unit} 

scala> x ? { println } 
!! 

scala> y ? { println } 

ताकि आप तो कर सकते थे लिखें:

some ? { _.toString } 

बिल्डिंग (रिकर्सिवली) SOC के जवाब पर, आप ऊपर के उदाहरण में x पर पैटर्न मैच परिष्कृत करने के लिए क्या कर सकते हैं ?x के प्रकार के आधार पर oes। : डी

+0

यह अच्छा है! अगर आप 'eq' ne' ऑपरेटरों कि इस जवाब का सार के रूप में समझा जा सकता है और', जो और भी अधिक उपयोगी होगा – asgs

+1

https://stackoverflow.com/questions/10066927/what-is-the-difference-between- एक-nenull और एक-शून्य-इन-स्केला – axel22

6

आप कुछ रैपर स्वयं लिख सकते हैं या एक विकल्प प्रकार का उपयोग कर सकते हैं।

मैं वास्तव में null के लिए जांच नहीं करता। यदि कहीं null है, तो आपको इसे ठीक करना चाहिए और इसके चारों ओर चेक बनाना नहीं चाहिए। axel22 के जवाब के शीर्ष पर

भवन:

implicit def any2hm(x: Any) = new { 
    def ? = x match { 
    case null => false 
    case false => false 
    case 0 => false 
    case s: String if s.isEmpty => false 
    case _ => true 
    } 
} 

संपादित करें: यह या तो संकलक दुर्घटना करने लगता है या काम नहीं करता। मैं जांच करूंगा।

+1

समस्या 'x' के रूप में घोषित करने के लिए' Any' कि यह '?' दायरे में विधि के लिए 2 अंतर्निहित रूपांतरण का परिचय है। – axel22

+0

क्या होगा यदि कुछ जावा स्ट्रिंग प्रकार है? ऐसा लगता है कि स्काला में ग्रोवी की समेकन की कमी है। – ace

+0

मुझे खेद है, लेकिन मैं दोनों उत्तरों का पालन नहीं कर रहा हूं लेकिन कोशिश करने के लिए धन्यवाद। मैं बस सरल समाधान की तलाश में था। – ace

33

ठीक है, Booleannull नहीं हो सकता है, जब तक कि एक प्रकार पैरामीटर के रूप में पारित न हो। null को संभालने का तरीका इसे Option में परिवर्तित करना है, और उसके बाद सभी Option सामान का उपयोग करें। उदाहरण के लिए:

Option(some) foreach { s => println(s) } 
Option(some) getOrElse defaultValue 

के बाद से स्काला स्थिर प्रकार है, एक बात नहीं हो सकता "कोई शून्य या रिक्त स्ट्रिंग है या शून्य संख्या आदि"। आप Any पास कर सकते हैं जो उन चीजों में से कोई भी हो सकता है, लेकिन फिर भी आपको प्रत्येक प्रकार से मिलान करना होगा ताकि वैसे भी कुछ भी उपयोगी हो सके। यदि आप खुद को इस स्थिति में पाते हैं, तो संभवतः आप बेवकूफ स्काला नहीं कर रहे हैं।

6

आप extempore's null-safe coalescing operator का उपयोग करते हैं, तो आप अपने str उदाहरण लिख सकता है

val str = ?:(some)(_.toString)() 

के रूप में यह भी null बारे में है (इस प्रकार "वालों") में चिंता किए बिना श्रृंखला के लिए आप की अनुमति देता है:

val c = ?:(some)(_.toString)(_.length)() 
के

बेशक, यह उत्तर केवल आपके प्रश्न के दूसरे भाग को संबोधित करता है।

6

जो आप पूछते हैं वह ग्रूवी के Safe Navigation Operator (?.) की लाइन में है, andand gem रूबी, या accessor variant of the existential operator (?.) कॉफीस्क्रिप्ट के लिए है।इस तरह के मामलों के लिए, मैं आम तौर पर मेरी RichOption[T] की ? विधि है, जो परिभाषित किया गया है के रूप में

class RichOption[T](option: Option[T]) { 
    def ?[V](f: T => Option[V]): Option[V] = option match { 
    case Some(v) => f(v) 
    case _ => None 
    } 
} 

implicit def option2RichOption[T](option: Option[T]): RichOption[T] = 
    new RichOption[T](option) 

इस प्रकार

scala> val xs = None 
xs: None.type = None 

scala> xs.?(_ => Option("gotcha")) 
res1: Option[java.lang.String] = None 

scala> val ys = Some(1) 
ys: Some[Int] = Some(1) 

scala> ys.?(x => Some(x * 2)) 
res2: Option[Int] = Some(2) 
0

इस प्रकार पैटर्न मिलान का उपयोग करना के रूप में जवाब के एक जोड़े में सुझाव का उपयोग करें और इस्तेमाल किया यहाँ एक अच्छा है दृष्टिकोण:

val some = Option(getSomething()) 
    some match { 
    case Some(theValue) => doSomethingWith(theValue) 
    case None   => println("Whoops, didn't get anything useful back") 
    } 

लेकिन, थोड़ा वर्बोज़।

मैं map निम्नलिखित तरीके से एक Option करना पसंद करते हैं:

Option(getSomething()) map (something -> doSomethingWith(something))

एक लाइनर, लघु, स्पष्ट।

इसका कारण यह है कि विकल्प को some kind of collection के रूप में देखा जा सकता है - संग्रह के कुछ विशेष हिमपात का टुकड़ा जिसमें शून्य तत्व या एक प्रकार का बिल्कुल तत्व होता है और जैसा कि आप एक सूची [ए] सूची [बी] में मानचित्र कर सकते हैं ], आप विकल्प [ए] को एक विकल्प [ए] में मैप कर सकते हैं। इसका अर्थ यह है कि यदि आपका विकल्प [ए] परिभाषित किया गया है, यानी यह कुछ [ए] है, नतीजा कुछ है [बी], अन्यथा यह कोई नहीं है। यह वास्तव में शक्तिशाली है!

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