समस्या से ऊपर है कि आपके निहित रूपांतरण collectionExtras
प्राप्त ऑब्जेक्ट प्रकार जानकारी खोने के लिए कारण बनता है। विशेष रूप से, उपर्युक्त समाधान में, कंक्रीट संग्रह प्रकार खो जाता है क्योंकि आप इसे Iterable[A]
प्रकार का ऑब्जेक्ट पास कर रहे हैं - इस बिंदु से, कंपाइलर अब xs
के वास्तविक प्रकार को नहीं जानता है। हालांकि बिल्डर फैक्टरी CanBuildFrom
प्रोग्रामेटिक रूप से सुनिश्चित करता है कि संग्रह का गतिशील प्रकार सही है (आपको वास्तव में Vector
मिलता है), स्थिर रूप से, संकलक केवल zipWith
कुछ Iterable
देता है।
इस समस्या को हल करने के लिए, अंतर्निहित रूपांतरण होने के बजाय Iterable[A]
लें, इसे IterableLike[A, Repr]
लें। क्यूं कर?
Iterable[A] extends IterableLike[A, Iterable[A]]
Iterable
साथ अंतर यह है कि इस IterableLike[A, Repr]
Repr
के रूप में ठोस संग्रह प्रकार रहता है:
Iterable[A]
आमतौर पर की तरह कुछ के रूप में घोषित किया गया है। सबसे ठोस संग्रह, Iterable[A]
में मिश्रण के अलावा, यह भी विशेषता IterableLike[A, Repr]
में मिश्रण, नीचे की तरह, उनके ठोस प्रकार के साथ Repr
की जगह:
Vector[A] extends Iterable[A] with IterableLike[A, Vector[A]]
वे क्या कर सकते हैं इस वजह प्रकार पैरामीटर Repr
covariant के रूप में घोषित किया गया है।
लंबी कहानी संक्षेप में, IterableLike
कारणों का उपयोग कर आप ठोस संग्रह प्रकार की जानकारी रखने के (कि Repr
है) के आसपास है और इसका इस्तेमाल करते हैं जब आप zipWith
परिभाषित करने के लिए अंतर्निहित रूपांतरण - ध्यान दें कि बिल्डर कारखाने CanBuildFrom
अब के लिए Repr
Iterable[A]
के बजाय शामिल होंगे पहले प्रकार पैरामीटर, उचित अंतर्निहित वस्तु के कारण हल किया जाना:
import collection._
import collection.generic._
implicit def collectionExtras[A, Repr](xs: IterableLike[A, Repr]) = new {
def zipWith[B, C, That](ys: Iterable[B])(f: (A, B) => C)(implicit cbf: CanBuildFrom[Repr, C, That]) = {
val builder = cbf(xs.repr)
val (i, j) = (xs.iterator, ys.iterator)
while(i.hasNext && j.hasNext) {
builder += f(i.next, j.next)
}
builder.result
}
}
अपने प्रश्न तैयार करने और अधिक ध्यान से पढ़ना ("? कैसे एक zipWith विधि है कि यह करने के लिए पारित किया उन लोगों के रूप संग्रह के एक ही प्रकार रिटर्न लिखने के लिए"), ऐसा लगता है कि आप एक ही प्रकार के संग्रह चाहते हैं आयन के रूप में zipWith
पास हो गया, निहित रूपांतरण के लिए, यह ys
जैसा ही प्रकार है।
import collection._
import collection.generic._
implicit def collectionExtras[A](xs: Iterable[A]) = new {
def zipWith[B, C, That, Repr](ys: IterableLike[B, Repr])(f: (A, B) => C)(implicit cbf: CanBuildFrom[Repr, C, That]) = {
val builder = cbf(ys.repr)
val (i, j) = (xs.iterator, ys.iterator)
while(i.hasNext && j.hasNext) {
builder += f(i.next, j.next)
}
builder.result
}
}
परिणामों के साथ
:
scala> immutable.Vector(2, 2, 2).zipWith(mutable.ArrayBuffer(4, 4, 4))(_ * _)
res1: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(8, 8, 8)
'new {def foo =} 'संरचनात्मक प्रकार का मान उत्पन्न करता है, जिसे प्रतिबिंब के माध्यम से बुलाया जाता है; इससे बचने के लिए, एक विशेषता ZipWith में हस्ताक्षर घोषित करें, और इस विशेषता का एक उदाहरण वापस करें। यह प्रश्न और सभी समाधानों पर लागू होता है। – Blaisorblade