2010-03-01 9 views
9

मैं एक त्रुटि क्यों मिलता है जब मैं बजाय _ का उपयोग कर एक नामित पहचानकर्ता का उपयोग करके देखें?स्काला में, `_` का उपयोग कर और एक नामित पहचानकर्ता का उपयोग करके के बीच क्या अंतर है?

scala> res0 
res25: List[Int] = List(1, 2, 3, 4, 5) 

scala> res0.map(_=>"item "+_.toString) 
<console>:6: error: missing parameter type for expanded function ((x$2) => "item 
".$plus(x$2.toString)) 
     res0.map(_=>"item "+_.toString) 
         ^

scala> res0.map(i=>"item "+i.toString) 
res29: List[java.lang.String] = List(item 1, item 2, item 3, item 4, item 5) 

उत्तर

18

वेरिएबल नामों के स्थान पर उपयोग किए गए अंडरस्कोर विशेष हैं; एनथ अंडरस्कोर का अर्थ अज्ञात फ़ंक्शन के लिए एनएच तर्क है। यदि आप ऐसा करते

List(1, 2, 3).map(x => x + 1) 

List(1, 2, 3).map(_ + 1) 

लेकिन,:: तो निम्नलिखित बराबर हैं

List(1, 2, 3).map(_ => _ + 1) 

तो फिर तुम एक समारोह है कि इसकी एक तर्क पर ध्यान नहीं देता और समारोह _ + 1 द्वारा परिभाषित रिटर्न के साथ इस सूची मानचित्रण कर रहे हैं। (यह विशिष्ट उदाहरण संकलन नहीं करेगा क्योंकि संकलक अनुमान नहीं लगा सकता दूसरे अंडरस्कोर है कि किस प्रकार।) का नाम दिया मानकों के साथ एक बराबर उदाहरण जैसा दिखाई देगा:,

List(1, 2, 3).map(x => { y => y + 1 }) 

संक्षेप में एक समारोह के तर्क सूची में अंडरस्कोर का उपयोग कर का मतलब है "मैं इस समारोह के शरीर में इन तर्कों को अनदेखा कर रहा हूं।" शरीर में उनका उपयोग करना मतलब है "कंपाइलर, कृपया मेरे लिए एक तर्क सूची उत्पन्न करें।" दो उपयोग बहुत अच्छी तरह से मिश्रण नहीं करते हैं।

+1

@Scoobie बस इसे मजबूत करने के लिए, अंडरस्कोर स्केल में कई _different_ उद्देश्यों के लिए उपयोग किया जाता है। जैसा कि डेविड ने समझाया, आपके उदाहरण में प्रत्येक उपयोग वास्तव में एक अलग अर्थ है। अन्य अर्थ भी हैं - अंडरस्कोर, स्कैला में, ऑपरेटर अधिभार से उत्पन्न होने वाली समस्याओं का एक बहुत अच्छा उदाहरण है। जबकि मुझे पहले इसके साथ समस्याएं थीं, मैं ईमानदारी से कह सकता हूं कि मैंने कभी इस पर सुधार करने के किसी तरीके के बारे में सोचा नहीं है। –

3

यदि आप पहचानकर्ता को बांधने वाले नहीं हैं, तो बस उस भाग को छोड़ दें।

res0.map("item "+_.toString) 
4

अन्य उत्तर की मदद के लिए यहाँ कुछ दिखा उदाहरण हैं जब '_' का उपयोग कर एक प्लेसहोल्डर पैरामीटर के रूप में है कि आपको "लापता पैरामीटर प्रकार" कुछ मामलों में मिलता है।

स्काला के प्रकार निष्कर्ष अपने संदर्भ के आधार पर एक अभिव्यक्ति की 'उम्मीद' प्रकार समझता है। यदि कोई संदर्भ नहीं है, तो यह पैरामीटर के प्रकार का अनुमान नहीं लगा सकता है। सूचना त्रुटि संदेश में _ के पहले और दूसरे उदाहरणों संकलक उत्पन्न पहचानकर्ता x$1 और x$2 बदल दिए जाते हैं।

scala> _ + _ 
<console>:5: error: missing parameter type for expanded function ((x$1, x$2) => x$1.$plus(x$2)) 
     _ + _ 
    ^
<console>:5: error: missing parameter type for expanded function ((x$1: <error>, x$2) => x$1.$plus(x$2)) 
     _ + _ 
     ^

पूरे अभिव्यक्ति के लिए एक प्रकार जोड़ना जोड़ना inferencer मदद करने के लिए पर्याप्त संदर्भ प्रदान करता है: वैकल्पिक रूप से

scala> (_ + _) : ((Int, Int) => Int) 
res3: (Int, Int) => Int = <function2> 

, आप प्रत्येक पैरामीटर प्लेसहोल्डर करने के लिए एक प्रकार जोड़ना जोड़ सकते हैं:

scala> (_: Int) + (_: Int)   
res4: (Int, Int) => Int = <function2> 

प्रदान किए गए तर्क तर्कों के साथ नीचे दिए गए फ़ंक्शन कॉल में, संदर्भ असंबद्ध है और फ़ंक्शन प्रकार अनुमानित है।

scala> def bar[A, R](a1: A, a2: A, f: (A, A) => R) = f(a1, a2) 
bar: [A,R](a1: A,a2: A,f: (A, A) => R)R 

scala> bar[Int, Int](1, 1, _ + _) 
res5: Int = 2 

हालांकि, अगर हम प्रकार पैरामीटर अनुमान लगाने के लिए, अगर विफल रहता है संकलक से पूछते हैं:

scala> bar(1, 1, _ + _)   
<console>:7: error: missing parameter type for expanded function ((x$1, x$2) => x$1.$plus(x$2)) 
     bar(1, 1, _ + _) 
       ^
<console>:7: error: missing parameter type for expanded function ((x$1: <error>, x$2) => x$1.$plus(x$2)) 
     bar(1, 1, _ + _) 
        ^

हम यह मदद कर सकते हैं, हालांकि, पैरामीटर सूचियों currying द्वारा। यहां, पहली पैरामीटर सूची (1, 1) पर तर्क, अनुमान लगाएं कि प्रकार पैरामीटर AInt होना चाहिए। यह तब जानता है कि तर्क f का प्रकार (Int, Int) => ?) होना चाहिए, और वापसी प्रकार R को पूर्णांक के परिणामस्वरूप Int के रूप में अनुमानित किया गया है। आप एक ही मानक पुस्तकालय में Traversable.flatMap में इस्तेमाल किया दृष्टिकोण देखेंगे।

scala> def foo[A, R](a1: A, a2: A)(f: (A, A) => R) = f(a1, a2) 
foo: [A,R](a1: A,a2: A)(f: (A, A) => R)R 

scala> foo[Int, Int](1, 1) { _ + _ } 
res1: Int = 2 

scala> foo(1, 1) { _ + _ } 
res0: Int = 2 
संबंधित मुद्दे

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