2017-01-22 1 views
5

私はPredef.StringCanBuildFrom私がCanBuildFrom私のコードで行っていた前提を壊す驚くべき実装の間につまずいた。Predef.StringCanBuildFromの動作

implicit def stringCanBuildFrom: CanBuildFrom[String, Char, String] = 
    new CanBuildFrom[String, Char, String] { 
     def apply(from: String) = apply() 
     def apply() = mutable.StringBuilder.newBuilder 
} 

apply(String)は、単にパラメータを無視することは全く不自然と思われる:ここでの実装です。私には、正しい実装は

implicit def stringCanBuildFrom: CanBuildFrom[String, Char, String] = 
    new CanBuildFrom[String, Char, String] { 
     def apply(from: String) = apply() ++= from 
     def apply() = mutable.StringBuilder.newBuilder 
} 

する必要がありますが、それは私が、私は言語が存在するためことを発見したのはONY一人を信じることができないように些細なようです。私はこれについて問題を開くように誘惑されましたが、私が提案したことをしないという正当な理由がなければ、教えてください!

答えて

3

apply(from)の目的を誤解していると思います。

それのマニュアルは言う:

コレクションのリクエストに応じて新しいビルダーを作成します。
@param作成するビルダーを要求するコレクション。
@returnタイプElemのタイプToのコレクションのビルダー。コレクションフレームワークでは通常、 のものが配置され、作成されたビルダーは同じ 種類のコレクションをfromとして作成します。

これは、コレクションのランタイム・タイプを使用してBuilderを解決し、元のコレクションから補助データをコピーするために使用されます。たとえば、scala.collection.generic.GenTraversableFactory#GenericCanBuildFromの実装は単純にdef apply(from: Coll) = from.genericBuilder[A]です。あなたが見るように、実際のデータは引数コレクションからコピーされません。

実は、CanBuildFromの実装がmapflatMapおよびその他の一般的な機能の標準実装のための間違った結果を生成します:

import scala.collection.generic.CanBuildFrom 
import scala.collection.mutable 

implicit def stringCanBuildFrom: CanBuildFrom[String, Char, String] = 
    new CanBuildFrom[String, Char, String] { 
    def apply(from: String) = apply() ++= from 
    def apply() = mutable.StringBuilder.newBuilder 
    } 

scala> "foo".map(identity)(stringCanBuildFrom) 
res1: String = foofoo 
+0

うーんを、私は使用法のより多くの例を読んでいる必要があります。そうです、彼らは常にビルダーが空に初期化されていると仮定しており、あなたの例では重複した '' foo ''を説明しています。乾杯:) – Dici