2014-12-10 7 views
5

इस कोड का उपयोग करएक अंडरस्कोर

(1 to 30).foreach { x => 
    println(x) 
    println 
} 

मैं क्या उम्मीद थी करता है एक लैम्ब्डा अभिव्यक्ति का निर्माण: यह रिक्त स्थान के साथ बीच-बीच में 130 के प्रत्येक, प्रिंट करता है। मैं यहाँ क्या हो रहा है पर बहुत स्पष्ट कर रहा हूँ, मुझे लगता है कि: मैं एक गुमनाम समारोह है कि पहले अपने तर्क प्रिंट, और फिर एक रिक्त पंक्ति प्रिंट गुजर रहा हूँ।

(1 to 30).foreach { 
    println _ 
    println 
} 

यह मेरे लिए बराबर दिखता है:

क्या मुझे समझ नहीं आता क्यों यह भी ऐसा ही नहीं करता है। अंडरस्कोर को फ़ंक्शन के लिए पहले और एकमात्र तर्क का प्रतिनिधित्व करना चाहिए; और फ़ंक्शन इसके तर्क को प्रिंट करता है, और फिर रिक्त रेखा प्रिंट करता है। लेकिन जब मैं इस दूसरे संस्करण को चलाता हूं, तो मुझे रिक्त रेखाएं नहीं मिलती हैं।

क्या इस अंतर का कारण बनता है?

उत्तर

5

पहले संस्करण का सीधा है:

  1. पहली पंक्ति में, x पर लागू println
  2. दूसरी पंक्ति में, कोई तर्क println (इस अतिरिक्त न्यू लाइन प्रिंट) लागू होते हैं।
दूसरे संस्करण के साथ

आप को प्रभावी ढंग से स्काला बता यह करने के लिए:

  1. पहली पंक्ति में, println() से एक समारोह वस्तु को परिभाषित। इसके बाद, इस नव निर्मित वस्तु के साथ कुछ भी नहीं करें।
  2. दूसरी पंक्ति में, तर्क ( अनुक्रम के तत्व) को println लागू होते हैं।

भ्रम धारणा से उत्पन्न होता है कि println(x) और println _ समकक्ष हैं। वे अलग हैं।funcId _ सिंटैक्स funcId के आधार पर एक नया फ़ंक्शन परिभाषित करता है, यह फ़ंक्शन को कॉल करते समय "अंडरस्कोर तर्क" नोटेशन का उपयोग करने जैसा नहीं है।

3

यहां कई चीजें चल रही हैं।

सबसे पहले सभी पैरामीटर प्लेसहोल्डर वाक्य रचना के केवल लैम्ब्डा परिभाषा के बाहरी कोष्ठकों के भीतर इस्तेमाल किया जा सकता। इसका उपयोग लैम्बडा परिभाषा के भीतर किए जाने वाले विधि कॉल के कोष्ठक के भीतर नहीं किया जा सकता है।

यहाँ इस बात को प्रदर्शित करने के एक उदाहरण है।

val a = (1 to 10).map(_ + 1) 

यह काम करेगा।

val b = (1 to 10).map(math.sin(_ + 1)) 

यह काम नहीं करेगा।

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

उदाहरण

(1 to 10).foreach(println _) 

के लिए कार्यात्मक रूप

val a = println (_ : Int) 
(1 to 10).foreach(a) 

इसके अलावा जब एक विधि नाम लैम्ब्डा अभिव्यक्ति अंडरस्कोर छोड़ा जा सकता है के भीतर प्रयोग किया जाता है के बराबर है। स्कैला अभी भी आंशिक रूप से लागू विधि उत्पन्न करेगा।

इसलिए

(1 to 10).foreach(println) 

इसलिए अपने कोड

val a = println (_ : Int) 
    (1 to 10).foreach{ 
    a 
    a 
    } 

के बराबर है और क्योंकि {आ} एक देता है, यह

के बराबर है

(1 to 10).foreach(println _) 

और के बराबर है

val a = println (_ : Int) 
(1 to 10).foreach(a) 
0

अन्य उत्तर करने के लिए जोड़ने के लिए, वहाँ वास्तव में println(_) उपयोग करने के लिए एक तरह से मौजूद है और x पैरामीटर घोषित करने के लिए नहीं:

(1 to 30).foreach { 
    (println(_: Int)) 
    .andThen(_ => println) 
} 

यहाँ foreach पैरामीटर, समारोह है, जो सबसे पहले सीमा तत्व के लिए println(_) का आह्वान है और फिर println(Int) परिणाम गुजरता (जो (): Unit है) किसी अन्य फ़ंक्शन, _ => println पर, जो इसके तर्क को अनदेखा करता है और नई लाइन प्रिंट करता है।

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