2016-03-01 25 views
9

मेरे पास एक साधारण फैक्ट्री पैटर्न है जहां कार्यान्वयन ओवरलोड रिज़ॉल्यूशन के माध्यम से निर्धारित किया जाता है। समस्या यह है कि कोटलिन कंपाइलर इनलाइन लैम्ब्डा के लिए "ओवरलोड रिज़ॉल्यूशन अस्पष्टता .." के साथ शिकायत करता है।कोटलिन: इनलाइन लैम्ब्डा और ओवरलोड रिज़ॉल्यूशन अस्पष्टता

class Foo(){ 
    companion object Factory { 
     fun create(x: Int, f: (Int) -> Double) = 2.0 
     fun create(x: Int, f: (Int) -> Int) = 1 
    } 
} 

fun main(args:Array<String>){ 
    val a = Foo.create(1,::fromDouble) //OK 
    val b = Foo.create(1,::fromInt) //OK 
    val ambiguous = Foo.create(1){i -> 1.0} //Overload resolution ambiguity? 
} 


fun fromDouble(int:Int) = 1.0 
fun fromInt(int:Int) = 1 

कोटलिन कंपाइलर ओवरलोड रिज़ॉल्यूशन को कैसे हल करता है और इनलाइन लैम्ब्डा को अस्पष्ट क्यों माना जाता है?

+4

यह एक बग प्रतीत होता है, क्योंकि अगर मैंने लैम्ब्डा को '{i: Int -> 1.0} के रूप में (int) -> डबल' की तरह अस्पष्टता नहीं दी है, लेकिन यह कहता है कि कास्ट की आवश्यकता नहीं है। इसके अलावा, अगर मैं लैम्ब्डा को 'वैल एल = {i: Int -> 1.0}' में निकालता हूं और इसका उपयोग करता हूं, तो फिर कोई अस्पष्टता नहीं होती है। कृपया इस समस्या के लिए बग ट्रैकर खोजें और यदि यह वहां कोई नया फ़ाइल नहीं है: https://youtrack.jetbrains.com/issues/KT – hotkey

+1

एक और दिलचस्प बात यह है कि अगर आप लैम्ब्डा को @hotkey के रूप में डालते हैं, तो आईडीई बताएगा आप यह जरूरी नहीं है कि यह आवश्यक नहीं है। लेकिन जिस क्षण आप इसे हटाते हैं, वह अस्पष्टता के बारे में शिकायत करता है। –

+1

इनपुट के लिए धन्यवाद! यह पता चला कि यह शायद एक बग था। Https://youtrack.jetbrains.com/issue/KT-11265 –

उत्तर

4

कोटलिन कंपाइलर केवल एक बार प्रत्येक अभिव्यक्ति को हल करता है। तो जब संकलक लैम्ब्डा अभिव्यक्ति के लिए संकल्प शुरू करता है, तो उसे लैम्ब्डा तर्कों के प्रकार पता होना चाहिए। इस कंपाइलर के कारण create से पहले इसे लैम्ब्डा के अंदर देखना शुरू होता है।

उदाहरण:

fun foo(f: (Int) -> Int) = 1 
fun foo(f: (String) -> String) = "" 
val bar = foo { 
    println(it) 
    5 
} 

यहाँ हम कार्यों foo से एक का चयन नहीं कर सकते क्योंकि उनमें से कोई भी एक और है कि अधिक विशिष्ट है, इसलिए हम लैम्ब्डा अभिव्यक्ति के लिए संकल्प शुरू नहीं कर सकते क्योंकि हम नहीं जानते कि it के लिए टाइप करें।

आपके उदाहरण में यह विशेष कार्य चुनने से पहले लैम्ब्डा के लिए संकल्प शुरू करना संभव है क्योंकि लैम्ब्डा तर्कों के सभी संभावित कार्यों के प्रकार समान हैं। लेकिन यह अनौपचारिक तर्क है जिसे लागू करना मुश्किल हो सकता है।

+0

पर एक रिपोर्ट दायर की गई यह एक बमर है। लैम्बडा पर ओवरलोड रिज़ॉल्यूशन संख्यात्मक अनुप्रयोग के लिए बहुत उपयोगी है। मान लें कि मेरे पास एक मैट्रिक्स क्लास है जो फ्लोट, डबल और इंट पर काम करती है। "ओवरलोड रिज़ॉल्यूशन" इंस्टेंसिंग के साथ 'वैल एमएस = Mat44 {i, j -> 1.0}' होगा, अब मुझे 'वैल एमएस = Mat44 ({i: Int, j: Int -> 1.0} लिखने के लिए मजबूर होना है (Int, Int) -> डबल) 'जो कि इस तरह के एक छोटे से काम के लिए सिर्फ सादा और मूर्खतापूर्ण verbose है। एक महान स्पष्टीकरण के लिए बहुत धन्यवाद @erokhins! –

+0

वर्कअराउंड के रूप में आप विभिन्न नामों के साथ फ़ंक्शन बना सकते हैं: 'मजेदार Mat44Int2Double (f: (Int, int) -> डबल) = Mat44 (f) '। लेकिन यह सुरुचिपूर्ण नहीं है ... – erokhins

+0

हाँ, मुझे पुराने पुराने एएनएसआई सी दिनों की याद दिलाता है :) –

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