2012-12-14 16 views
12

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

val fl = (x: Int) => { 
    println("Add 25 to "+x) 
    x + 25 
} 

हालांकि, जब आप इसे एक एकल तर्क समारोह को पारित, तुम समारोह शाब्दिक के लिए आवश्यक घुंघराले ब्रेस अनदेखा कर सकते हैं।

किसी दिए गए समारोह च के लिए

तो,

def f(fl: Int => Int) { 
    println("Result is "+ fl(5)) 
} 

आप, च() इस तरह कॉल कर सकते हैं

f(x=> { 
    println("Add 25 to "+x) 
    x + 25 
}) 
------------------------- 
Add 25 to 5 
Result: 30 

या जब आप समारोह कॉल में कोष्ठक के बजाय घुंघराले ब्रेसिज़ उपयोग करते हैं, आप कर सकते हैं समारोह शाब्दिक से आंतरिक घुंघराले ब्रेसिज़ को हटा दें। तो निम्नलिखित कोड भी काम करेगा,

f{ x=> 
    println("Add 25 to "+x) 
    x + 25 
} 

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

उत्तर

20

कुछ सरल वाक्यविन्यास नियम हैं। Spec का परिशिष्ट perusing लायक है।

एक फ़ंक्शन शाब्दिक या अज्ञात फ़ंक्शन (6.23) x => Expr या x => Block जैसा दिखता है, इस पर निर्भर करता है कि संदर्भ क्रमशः एक expr या ResultExpr है या नहीं।

एक फ़ंक्शन एप्लिकेशन (6.6) f(Expr, Expr) या f BlockExpr, यानी f{ Block } जैसा दिखेगा। यही है, एक ब्लॉकएक्सप्रो {...} के अंदर ब्लॉक स्टेटमेंट का सिर्फ एक अनुक्रम है।

जब आप f(g) पर कॉल करते हैं, तो जी एक एक्सप्रप्रस है, इसलिए फ़ंक्शन शाब्दिक, x => Expr। Expr एक BlockExpr, x => { ... } हो सकता है।

जब आप f{ Block } पर कॉल करते हैं, तो f { x => ... } में ब्लॉक के ResultExpr में फ़ंक्शन शाब्दिक होता है (जो केवल विवरणों का अनुक्रम है, कोई ब्रेसिज़ आवश्यक नहीं है)।

यहाँ, यह स्पष्ट है कि शीघ्र समारोह एक ब्लॉक के नीचे स्थित है:

scala> def m(x: Int=>Int) = x(5) 
m: (x: Int => Int)Int 

scala> m { 
    | val y = 7 
    | x => // no brace 
    | x+y+1 
    | } 
res0: Int = 13 
+0

इस विवरण मैं खोज रहा था है। इसके अलावा, आपके द्वारा हाइलाइट किए गए चश्मे के अनुभागों के अलावा, कोई भी बेहतर समझ के लिए ब्लॉक (6.11) अनुभाग का संदर्भ ले सकता है। – jafaeldon

+0

गीट उत्तर, मैं इसे बेहतर समझा नहीं सकता था। इसे ऊपर उठाया चीयर्स! – wleao

8

यह उन चीजों में से एक है जो स्कैला को मेरे लिए सुंदर बनाती हैं।

आपके सवाल का सरल जवाब है:

कोष्ठक() एकल लाइन निर्माण के लिए होती हैं। उदाहरण के लिए, यह काम करता है:

def f(fl: Int => Int) { 
    println("Result is " + fl(5)) 
    } 

    f(
    x => 
    x + 25) 

    f(x => x + 25) // single line 

और घुंघराले ब्रेसिज़ {} मल्टीलाइन कथन के लिए हैं। उदाहरण के लिए, इस काम करता है:

f { 
    x => 
    println("Add 25 to " + x) 
    x + 25 
} 

लेकिन इस कोड काम नहीं करता:

f ( 
    x => 
    println("Add 25 to " + x) 
    x + 25 
) 

संकलक निम्न संदेश के साथ शिकायत:

मान x यूनिट के एक सदस्य नहीं है संभावित कारण: हो सकता है कि अर्धविराम 'मान x' से पहले गायब हो?

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

यदि आप ऐसा करने का प्रयास करें:

f { x => println("Add 25 to " + x) x + 25 } 

संकलक संदेश के साथ आपको वापस मिल जाएगा: एक्स के सदस्य के रूप

value x is not a member of unit 

आपको लगता है कि वह खोजने की कोशिश कर रहा है मिलता है इकाई। पसंद:

f { println("Add 25 to " + x).x.+(25) } 

जो स्पष्ट रूप से गलत है।

आप भीतरी घुंघराले ब्रेसिज़, इस तरह जोड़ते हैं:

f ( 
    x => { 
    println("Add 25 to " + x) 
    x + 25 
    } 
) 

यह भी काम करेंगे, लेकिन आप अभी भी एक बहु बयान है कि घुंघराले ब्रेसिज़ के उपयोग से संकेत कर रहा है। तो संकलक जानता है कि आप पहले प्रिंट करना चाहते हैं और फिर 25 से x जोड़ें।

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

चीयर्स!