http://hongjiang.info/scala-canbuildfrom-detail/數組
在twitter上看到過的:http://www.dotkam.com/2012/05/08/scala-fun-with-canbuildfrom/
《快學Scala》這本書的p333頁有對CanBuildFrom這個隱式參數的解讀。app
1ide 2函數 3ui 4this 5spa 6.net |
|
先要弄清楚Repr這個類型參數的含義:意思是「展示類型」?
還有Builder這個trait,裏面定義了+=和result兩個方法。
//2013.2.19 補充,從下面這個例子分析
1 |
|
1 |
|
這句表達式被翻譯爲StringOps.map(...)
,除了顯式傳入的 Char => Int
的函數,後邊還有個隱式的參數:(scala.this.Predef.fallbackStringCanBuildFrom[Int])
看了一下 Predef裏面,沒有找到 fallbackStringCanBuildFrom ,卻是發現了
DummyImplicit 這個類,註釋裏有提到: @see scala.Array$, method `fallbackCanBuildFrom`
Array的伴生對象確實繼承了 FallbackArrayBuilding這個類,它裏面有個隱式轉換方法:
1 2 3 4 5 |
|
// 繼續,經過斷點跟蹤了一下,是在 LowPriorityImplicits 這個class裏定義了一些隱式轉換函數,跟上面的無關。
1 2 3 4 5 |
|
見下圖:
而map方法是在 TraversableLike 這個trait裏定義的:
把斷點設置在上面的 val b = bf(repr)
這一行,先看看repr這個變量在TraversableLike裏的定義,是一個函數,返回自身對象,造型爲Repr類型。
/** The collection of type $coll underlying this `TraversableLike` object. * By default this is implemented as the `TraversableLike` object itself, * but this can be overridden. */ def repr: Repr = this.asInstanceOf[Repr]
對於String來講,這個repr就是自身,bf(repr) 調用 CanBuildFrom.apply
方法,而fallbackStringCanBuildFrom
提供的builder是
Builder[A,IndexedSeq[A]]
類型,它的實現實際是 VectorBuilder
,見 IndexedSeq
類的伴生對象。
每一個集合都在其伴生對象裏提供了一個隱式的CanBuildFrom
對象。
builder建立好了目標類型的容器後,開始迭代當前容器執行f函數轉換,並將結果填入目標容器。
for(x <- this) b+= f(x)
這個for表達式轉化爲 StringOps.foreach(f:A=>B)
,實際調用的是 IndexedSeqOptimized.foreach(f:A=>B)
裏的邏輯,這個 foreach(func) 是override了 IterableLike 裏的foreach方法。
VectorBuilder
的result返回的是Vector類型,它也混入了IndexedSeq特質
scala> "abc".map(_+1) res0: scala.collection.immutable.IndexedSeq[Int] = Vector(98, 99, 100)
整個前因後果弄清楚了。另外,Vector是樹形數組,效率比較高。