2012-04-12 7 views
6

में प्रकार से एकत्र स्काला 2.9.1जेनेरिक साथ</p> <pre><code>def collectFirstOfT[T](la: List[_])(implicit m:Manifest[T]) : Option[T] = { la.collect{case x if m.erasure.isAssignableFrom(x.getClass) => x}. headOption.asInstanceOf[Option[T]]} class A class B </code></pre> <p>स्केला

में क्यों इस अभिव्यक्ति:

val oB:Option[B] = collectFirstOf(List(new A,new B)) 

compiles लेकिन कुछ (ए) एकत्र करता है, लेकिन

val oB =collectFirstOf[B](List(new A,new B)) 

ठीक काम करता है।

विकल्प से टी का अनुमान कैसे लगाया जाए [टी]?

उत्तर

3

आप दो अलग-अलग भागों, = के बाएं हाथ की ओर और अधिकार के रूप में निम्न पंक्ति को देखने के लिए है:

val oB: Option[B] = collectFirstOf(List(new A,new B)) 

क्या तुम यहाँ की उम्मीद कर रहे है कि collectFirstOf अभिव्यक्ति के प्रकार (रावल्यू) मूल्य ओबी के प्रकार से अनुमानित किया जाना चाहिए। कंपाइलर ऐसा नहीं कर सकता है। आपको विशेष रूप से कहना है कि आप किस प्रकार की उम्मीद कर रहे हैं। निम्नलिखित उदाहरण लें:

val v: Long = 1 + 4 

अभिव्यक्ति का प्रकार 1 + 4 एक इंट है। यह int तब एक लांग में परिवर्तित हो जाता है। कंपाइलर यह नहीं अनुमान लगाता है कि आप 1 या 4 को लंबे समय तक रखना चाहते हैं:

तो, अपनी समस्या को ठीक करने के लिए, आपको संकलक को यह बताना होगा कि आप किस प्रकार की अपेक्षा कर रहे हैं, अन्यथा यह मानता है java.lang.Object:

val oB = collectFirstOf[B](List(new A,new B)) 

तो प्रकट सही ढंग से सौंप दिया जाता है, और पूरी दुनिया के साथ अच्छी तरह से है। तो क्यों भी निम्नलिखित है संकलन: पहली नजर में

val oB:Option[B] = collectFirstOfT(List(new A,new B)) 
oB: Option[B] = Some([email protected]) 

, तो वह ऐसा प्रतीत होता है नहीं काम करना चाहिए, लेकिन यह नहीं करता है। इसका कारण यह है collectFirstOfT वास्तव में एक विकल्प [कुछ भी नहीं है], जो सुरक्षित रूप से एक विकल्प [बी] में बदला जा सकता रिटर्न है:

scala> val f = collectFirstOfT(List(new A,new B)) 
f: Option[Nothing] = Some([email protected]) 

scala> f.asInstanceOf[Option[B]] 
res4: Option[B] = Some([email protected]) 
+0

अच्छा पकड़ो! मैं फ़ंक्शन को याद करने से कैसे रोक सकता हूं? (आदर्श, इसे संकलित नहीं करना चाहिए) – jwinandy

+0

एक त्वरित और आसान तरीका एक स्पष्ट तर्क जोड़ना होगा, कक्षा: संग्रह फर्स्टऑफटी [टी] (सीएलएस: कक्षा [टी], ला: सूची [_]), फिर कॉल करें: संग्रह फर्स्टऑफटी (कक्षा ओएफ [बी], सूची (नया ए, नया बी))। यह अपेक्षित के रूप में एक विकल्प [बी] वापस करेगा। –

0

क्योंकि संकलक T से उपकरण से अनुमान नहीं लगा सकता है, इसलिए आपको इसे स्पष्ट रूप से लिखना होगा। पहले मामले में collect सभी सूची स्वीकार करता है।

+0

'टी' (या 'विकल्प [टी]') केवल वापसी प्रकार के लिए है। '{केस एक्स अगर m.erasure.isAssignableFrom (x.getClass) => x}' एक 'आंशिक कार्य है [-एनी, + कोई भी]'। – jwinandy

3

यह:

:

val oB:Option[B] = collectFirstOfT(List(new A,new B)) 

इस के बराबर है वैल ओबी: विकल्प [बी] = संग्रह फर्स्टऑफटी [कुछ भी नहीं) (सूची (नया ए, नया बी))

चूंकि Nothing सब कुछ का सबक्लास है, तो यह A से असाइन किया जा सकता है। हां, यह B से भी असाइन करने योग्य है, जिसका अर्थ है कि आप Option[Nothing] को Option[B] पर असाइन कर सकते हैं।

मजेदार तथ्य: यह सच है क्योंकि Option सह-संस्करण है। यदि यह नहीं था, तो T को B के रूप में अनुमानित किया जाना चाहिए, जो इसे काम करेगा।

मज़ा तथ्य 2: यह कोड कल के ट्रंक पर संकलित नहीं है।

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

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