2010-10-26 11 views
22

यह संभव है करने के लिए इस क्यों नहीं है:स्काला बताए Vals

def main(args:Array[String]) { 
    val whatever:String // Have it uninitialized here 

    if(someCondition) { 
     whatever = "final value" // Initialize it here 
    } 
} 

मुझे समझ नहीं आता क्यों यह कानूनी नहीं होना चाहिए। मुझे पता है कि मैं इसे var बना सकता हूं, लेकिन जब हम इसे घोषित करते हैं तो हमें val को प्रारंभ करना क्यों होगा? क्या इसे बाद में शुरू करने में सक्षम होने के लिए यह अधिक तार्किक प्रतीत नहीं होता है?

+0

संकलक कैसे सुनिश्चित करेगा कि यह वास्तव में अंतर्निहित है? हाँ, यह संभव है - लेकिन कठिन, और जरूरत नहीं है। – delnan

+2

क्योंकि प्रारंभिक बिंदु के बिंदु तक, मान * अनिर्धारित * है और केवल निम्न नियंत्रण प्रवाह के संदर्भ में समझ में आता है। कार्यात्मक प्रोग्रामिंग में, कोई अपरिभाषित मान नहीं हैं - और मूल्य - राज्य नहीं - केवल एकमात्र चीजें हैं जो महत्वपूर्ण हैं। – Dario

+0

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

उत्तर

38

आप कर सकते हैं:

val whatever = 
    if (someCondition) 
     "final value" 
    else 
     "other value" 
+1

और यदि कुछ कंडिशन को एक से अधिक मान सेट करने के लिए उपयोग करने की आवश्यकता है, तो आप टुपल्स और वैल्यू अपघटन का उपयोग कर सकते हैं। – andresp

3

क्योंकि 'वैल' का उद्देश्य पाठक (और संकलक) के लिए संकेत करने के लिए है: "यह मूल्य रहना होगा क्या यह जब तक इसे से बाहर चला जाता है के लिए आरंभ नहीं हो जाता अस्तित्व "

यह प्रारंभिकरण के बिना अधिक समझ में नहीं आता है।

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

9

उपयोग lazy val तो जैसे रों:

def main(args:Array[String]) { 
    lazy val whatever:String = if (someCondition) "final value" else "other value" 

    // ... 

    println(whatever) // will only initialize on first access 
} 
+1

यदि इकाई के अंदर असाइनमेंट यूनिट वापस करेगा। अगर एक और खंड के बिना यूनिट भी वापस आ जाएगा। मुझे लगता है कि आप उदाहरण संकलित नहीं करेंगे ... –

+0

सबमिट करने से पहले पढ़ें ... आप सही हैं। सही किया। –

7

क्या अन्य लोगों ने कहा के अलावा, ध्यान दें कि जावा की अनुमति देता है "खाली अंतिम" "चर" है, जो एक सुविधा मैं थोड़े याद आती है:

final Boolean isItChristmasYet; 

if (new Date().before(christmas)) { 
    isItChristmasYet = Boolean.FALSE; 
} else { 
    isItChristmasYet = Boolean.TRUE; 
} 

हालांकि, कंपाइलर में डेटा प्रवाह विश्लेषण के लिए धन्यवाद, javac आपको धारण नहीं होने पर whatever वैरिएबल को असाइन नहीं किया जाएगा।

+0

हाँ, मैं जावा से भी यही याद करता हूं। – Geo

+1

जिज्ञासा से, अनियमित वैरिएबल प्री-घोषित करके आपको वास्तव में क्या लाभ होता है? ऐसा नहीं है कि आप इसे वास्तव में प्रारंभ करने से पहले किसी भी तरह से इसका उपयोग कर सकते हैं ... –

+0

यह एक स्टाइलिस्ट चीज है, मैं अपने सभी स्थानीय लोगों को अपने दायरे के शीर्ष पर सामने की ओर घोषित करता था। मैं शायद अभी भी - कम से कम कभी-कभी - यदि स्कैला में खाली वलियां थीं। :) –

27

जावा समाधान वास्तव में, समस्या यह है कि नहीं सभी भाव मान वापस जाने के लिए एक समाधान नहीं है तो आप जावा में यह नहीं लिख सकते हैं:

final String whatever = if (someCondition) { 
    "final value" 
} else { 
    "other value" 
} 

तेजी से, जावा में प्रवृत्ति त्रिगुट ऑपरेटर का उपयोग करने के लिए है बजाय:

final String whatever = someCondition ? "final value" : "other value" 

कौन सा है कि सीमित उपयोग के मामले के लिए ठीक है, लेकिन पूरी तरह से अस्थिर एक बार आप स्विच बयान और कई निर्माताओं के साथ काम कर शुरू करते हैं।


स्कैला का दृष्टिकोण यहां अलग है। सभी ऑब्जेक्ट निर्माण अंततः एक "प्राथमिक" कन्स्ट्रक्टर के माध्यम से गुजरना चाहिए, सभी अभिव्यक्तियां एक मान लौटाती हैं (भले ही यह Unit है, जावा के Void के बराबर), और कन्स्ट्रक्टर इंजेक्शन दृढ़ता से अनुकूल है। इसके परिणामस्वरूप ऑब्जेक्ट ग्राफ़ को निर्देशित एसाइक्लिक ग्राफ के रूप में साफ रूप से बनाया जा रहा है, और यह अपरिवर्तनीय वस्तुओं के साथ बहुत अच्छी तरह से काम करता है।

आप यह भी जानना चाहते हैं कि अलग-अलग परिचालनों में चर को घोषित करना और परिभाषित करना सामान्य रूप से एक से अधिक धागे से निपटने के दौरान एक बुरा अभ्यास है - और जब आप कम से कम उम्मीद करते हैं तो आपको नल और दौड़ की स्थिति को उजागर करने के लिए कमजोर छोड़ सकता है (हालांकि वस्तु निर्माण के दौरान यह वास्तव में एक समस्या नहीं है)। अपरिवर्तनीय मूल्यों का परमाणु निर्माण इस तरह का एक पहलू है जिसमें कार्यात्मक भाषाएं समवर्तीकरण से निपटने में मदद करती हैं।

इसका यह भी अर्थ है कि स्कैला कंपाइलर जावा भाषा स्पेक से कुछ जटिल रूप से जटिल प्रवाह विश्लेषण से बच सकता है।

पहले कहा गया है, स्काला रास्ता ™ है:

val whatever = 
    if (someCondition) 
    "final value" 
    else 
    "other value" 

एक दृष्टिकोण है जो भी अन्य नियंत्रण संरचनाओं के लिए ऊपर मापता है:

val whatever = someCondition match { 
    case 1 => "one" 
    case 2 => "two" 
    case 3 => "three" 
    case _ => "other" 
} 

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