2016-08-29 11 views
5

में फ्लैटमैप घोषणा को समझना मैंने अभी List.flatMap घोषणा को देखा और इससे आश्चर्यचकित हुआ।सूची

final override def flatMap[B, That](f: A => GenTraversableOnce[B]) 
       (implicit bf: CanBuildFrom[List[A], B, That]): That 

कहाँ object List परिभाषित करता है:

implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, List[A]] = 
    ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] 

तो, अगर हम एक List पर flatMap आह्वान हम List मिल जाएगा और मैं That प्रकार में किसी भी बिंदु नहीं दिख रहा है, तो यह हमेशा के लिए निष्कर्ष निकाला की जाएगी List[B] (implicit की वजह से)।

+0

कि 'implicit' एक और अधिक स्थानीय एक, के लिए बनाता है कि साथ अधिरोहित जा सकता, मान लें, एक' Vector', या स्पष्ट रूप से एक पैरामीटर – Chirlo

+0

http देखें के रूप में पारित: // stackoverflow .com/a/1728140/5344058 जब यह मूल संग्रह –

+0

की तुलना में एक अलग प्रकार होने के लिए उपयोगी है, तो क्या आपने कभी फ्लैटमैप या मानचित्र के साथ 'collection.breakout' देखा है ... यह एक है इस निहित ओवरराइड करने का उदाहरण। –

उत्तर

5

तो, अगर हम एक List[A] पर flatMap आह्वान हम List[A] मिल जाएगा और मैं नहीं That प्रकार में किसी भी बिंदु देखें कि क्या वह हमेशा के लिए List[B]

एक तुम बात निष्कर्ष निकाला हो जाएगा करते हैं ' गायब है कि flatMap वास्तव में List[+A] पर परिभाषित नहीं किया गया है। इसे TraversableLike से विरासत में मिला है, जो स्केलस संग्रहों द्वारा उपयोग की जाने वाली विशेषता है। उनमें से प्रत्येक अंतर्निहित CanBuildFrom आपूर्ति कर सकता है जिसे एक अलग परिणामी संग्रह की आपूर्ति के लिए ओवरराइड किया जा सकता है।

आप आप एक कस्टम CanBuildFrom साथ क्या कर सकते की एक छोटा सा स्वाद चाहते हैं:

scala> :pa 
// Entering paste mode (ctrl-D to finish) 

import scala.collection.generic.CanBuildFrom 
import scala.collection.immutable._ 
import scala.collection.mutable 
import scala.{List, Vector} 

implicit val listToVectorCBF = new CanBuildFrom[List[Int], Int, Vector[Int]] { 
    override def apply(from: List[Int]): mutable.Builder[Int, Vector[Int]] = this.apply() 
    override def apply(): mutable.Builder[Int, Vector[Int]] = Vector.newBuilder 
} 

// Exiting paste mode, now interpreting. 

scala> List(1,2,3).flatMap(List(_)) 
res6: Vector[Int] = Vector(1, 2, 3) 
+0

लेकिन क्या मैं कुछ ऐसा प्राप्त करने के लिए अपना खुद का 'CanBuildFrom' आपूर्ति कर सकता हूं जो एक सेक भी नहीं है? – user3663882

+0

@ user3663882 कुछ भी आपको खुद को आपूर्ति करने से रोक नहीं रहा है। यह व्युत्पन्न कक्षाओं के लिए विधि को फिर से कार्यान्वित करने के बजाय बस अपना स्वयं का सीबीएफ निहित प्रदान करना आसान बनाता है। –

+0

@ user3663882 मैंने प्रदर्शन करने के लिए एक छोटा सा उदाहरण जोड़ा है। –

2

खैर ... यही कारण है कि implicit CanBuildFrom बजाय सीधे संरचना के विभिन्न प्रकार List और इस प्रकार एक बचत का निर्माण किया जा सकता है अतिरिक्त कदम निम्न उदाहरण को देखो देता है,

val list = List(List(1, 2, 3), List(4, 5, 6)) 

// now if we do a flatmap withtout overriding the implicit CanBuildFrom 
val newList = list.flatMap(l => l.map(i => (i,i))) 

// new list will be a List[(Int, Int)] 
// but what if you wanted a map 

val newMap = newList.toMap 

// But you actually needed to traverse the list twice in this case 

// But we can avoid the second traversal if we chose to override the implicit 
val newMap2 = list.flatMap(l => l.map(i => (i,i)))(collection.breakout)