2011-12-18 12 views
5
def foo(num:Int, str:String):Int = 1 

val bar = foo(3, _) // compiler complains "missing parameter type for expanded function ((x$1) => test(3, x$1))" 

val baz = foo(3, _:String) // compiles fine 

मुझे संदर्भ से inferrable दिखने पर मुझे _ के प्रकार को स्पष्ट रूप से निर्दिष्ट क्यों करना होगा?आंशिक रूप से लागू फ़ंक्शन परिभाषा में अनावश्यक पैरामीटर प्रकार की जानकारी

EDIT: डेविड सोर्गेल के सुझाव के बाद नाम टक्कर से बचने के लिए नामित किया गया।

उत्तर

3

सबसे पहले, "डीईएफ़ परीक्षण" और "वैल परीक्षण" बीच भ्रम की स्थिति से बचने के लिए, के बारे में करते हैं:

def foo(num:Int, str:String):Int = 1 

val bar = foo(3, _) // compiler complains "missing parameter type for expanded function ((x$1) => foo(3, x$1))" 

val baz = foo(3, _:String) // compiles fine 

क्या संदर्भ से inferrable है ही नहीं तर्क बार किसी तरह एक स्ट्रिंग के लिए परिवर्तनीय होना चाहिए है । यह विरासत के कारण हो सकता है (यदि स्ट्रिंग के बजाय आप वहां कुछ गैर-अंतिम प्रकार का उपयोग करते हैं), या एक अंतर्निहित रूपांतरण के कारण।

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

+1

नाम सुधार के लिए धन्यवाद लिख सकते हैं। लेकिन 'def foo (num: int) = 1; वैल बार = foo (_) 'ठीक संकलित करता है। इसलिए मुझे नहीं लगता कि विरासत या निहित रूपांतरण त्रुटियों का कारण बनते हैं। – xiefei

+0

हू - क्षमा करें, आगे प्रतिबिंब पर implicits के बारे में मेरा तर्क वैसे भी कोई मतलब नहीं है। कंपाइलर वास्तव में स्ट्रिंग होने के लिए बार तर्क के प्रकार का अनुमान लगा सकता है, और उसके बाद सामान्य रूप से बार को कॉल करते समय implicits को अनुमति देता है। –

3

मुझे लगता है कि दाऊद Soergel के विवरण अनिवार्य रूप से सही है: यदि प्रकार T स्ट्रिंग के लिए एक अंतर्निहित रूपांतरण तो है val bar = foo(3, _:T) है वैध, प्रकार T => Int, जो String => Int से संबंधित नहीं है के एक समारोह दे रही है।

क्यों संकलक एक समझदार धारणा (स्पष्ट टाइपिंग की अनुपस्थिति में) नहीं बनाता है कि वास्तव में विधि विधि (जो आपके प्रश्न का सार है) जैसा ही है, मुझे नहीं पता - मैं केवल अनुमान लगा सकता हूं क्योंकि यह भाषा की कल्पना को जटिल करेगा।

जहां कोई प्रकार निर्दिष्ट कर रहे हैं, अर्थात val bar = foo(_, _), यह संकलक यह व्याख्या के रूप में सरल ईटा-रूपांतरण, val bar = foo _ के रूप में ही है, जो एक String => Int देता है लगता है।

मेरे पसंदीदा मुहावरा बाएं हाथ की ओर समारोह प्रकार है, जो आप की अनुमति देता है को लाभ मिलता है देने के लिए किया जाएगा आसानी से bar के प्रकार को देखने के लिए:

val bar: String => Int = foo(3, _) 

आप फिर से एलर्जी हो, तो String शब्द टाइप करके, आप

val bar = (foo _).curried(3) 
+0

"स्काला स्पेक (2.8) का हिस्सा" अज्ञात कार्यों के लिए प्लेसहोल्डर सिंटेक्स "इस बारे में कोई जानकारी नहीं देता है कि" _ "का अनुमान किस प्रकार है। Spec की कमी इस कंपाइलर असंगतता का कारण हो सकता है। – xiefei

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