2014-10-07 8 views
10

क्या कोई समझा सकता है कि निम्नलिखित क्यों काम नहीं करते हैं। किसी भी तरह से toSet करते समय टाइप अनुमान के लिए कुछ जानकारी संकलित करता है, लेकिन मुझे समझ में नहीं आता क्यों।toSet और टाइप करें अनुमान

scala> case class Foo(id: Int, name: String) 
defined class Foo 

scala> val ids = List(1,2,3) 
ids: List[Int] = List(1, 2, 3) 

scala> ids.toSet.map(Foo(_, "bar")) 
<console>:11: error: missing parameter type for expanded function ((x$1) => Foo(x$1, "bar")) 
       ids.toSet.map(Foo(_, "bar")) 
           ^

scala> ids.map(Foo(_, "bar")).toSet 
res1: scala.collection.immutable.Set[Foo] = Set(Foo(1,bar), Foo(2,bar), Foo(3,bar)) 
+1

लगता है कि कंपाइलर को प्रकार को स्पष्ट करने में कुछ मदद की ज़रूरत है, 'ids.toSet.map (Foo (_: Int, "bar")) ' – jarandaf

+0

हां, लेकिन जब मैं करता हूं तो संकलक को जानकारी की आवश्यकता क्यों नहीं होती मानचित्र के बाद toSet ?? – regexp

+1

उलझन में, यह काम करता है, 'वैल ए = ids.toSet; a.map (Foo (_, "bar")) ' – elm

उत्तर

6

मान लीजिए मैं निम्नलिखित है:

trait Pet { 
    def name: String 
} 

case class Dog(name: String) extends Pet 

val someDogs: List[Dog] = List(Dog("Fido"), Dog("Rover"), Dog("Sam")) 

Set अपने प्रकार पैरामीटर में covariant नहीं है, लेकिन List है। इसका मतलब है कि अगर मेरे पास List[Dog] है तो मेरे पास List[Pet] भी है, लेकिन Set[Dog]Set[Pet] नहीं है। सुविधा के लिए, स्कैला आपको पर एक स्पष्ट प्रकार पैरामीटर प्रदान करके (या अन्य संग्रह प्रकार) से Set पर रूपांतरण के दौरान उथल-पुथल करने की अनुमति देता है। जब आप val a = ids.toSet; a.map(...) लिखते हैं, तो इस प्रकार का पैरामीटर अनुमानित है और आप ठीक हैं। जब आप ids.toSet.map(...) लिखते हैं, दूसरी ओर, यह अनुमानित नहीं है, और आप भाग्य से बाहर हैं।

scala> val twoPetSet: Set[Pet] = someDogs.toSet.take(2) 
twoPetSet: Set[Pet] = Set(Dog(Fido), Dog(Rover)) 

हालांकि यह नहीं करता है::

scala> val allDogSet: Set[Dog] = someDogs.toSet 
allDogSet: Set[Dog] = Set(Dog(Fido), Dog(Rover), Dog(Sam)) 

scala> val twoPetSet: Set[Pet] = allDogSet.take(2) 
<console>:14: error: type mismatch; 
found : scala.collection.immutable.Set[Dog] 
required: Set[Pet] 
Note: Dog <: Pet, but trait Set is invariant in type A. 
You may wish to investigate a wildcard type such as `_ <: Pet`. (SLS 3.2.10) 
     val twoPetSet: Set[Pet] = allDogSet.take(2) 
              ^

भ्रम इस लायक है

यह काम करने के लिए निम्नलिखित की अनुमति देता है? मुझे नहीं पता। लेकिन यह समझ में आता है, और यह संकल्प एपीआई डिजाइनर toSet के लिए बनाया गया निर्णय है, इसलिए हम इसके साथ अटक गए हैं।

+0

इस बारे में एक भ्रमित बात यह है कि एक प्रकार का अनुमान लगाने में असमर्थता 'toSet' को कंपाइलर द्वारा 'Foo (_," bar ") के लिए किसी प्रकार का अनुमान लगाने में असमर्थता के रूप में व्यक्त किया जाता है। सम्मेलन किसी भी दिशा में काम करता प्रतीत होता है: 'ids.toSet [Int] .map (Foo (_," bar ")) 'शिकायत नहीं करता है, और न ही' ids.toSet.map (Foo (_: Int, "बार")) '। –

+0

@ जो: मुद्दा यह है कि 'मानचित्र' को इसके तर्क के तर्क के प्रकार को जानने की आवश्यकता है। यदि जिस सेट को इसे कॉल किया जा रहा है उसे ज्ञात नहीं है या अभी तक अनुमानित नहीं किया गया है, तो आपको उस प्रकार को स्पष्ट रूप से प्रदान करना होगा। –

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