2017-01-07 1 views
0

暗黙的なCanBuildFromパラメータを使用すると、コレクションに対して1つの操作が行われた場合にのみ同じタイプのコレクションを返すことができます。もっと複雑なメソッドをパラメータ型と同じ型で返すようにする簡単な方法はありますか?あなたがIterableのサブタイプの有効なサブタイプにitemsのコレクション型と戻り値の型の両方を変更した場合、コードはまだコンパイルされますコレクションに対して複数の操作を実行した後、同じコレクションタイプを返します。

def trimCharacters(items: Iterable[String]): Iterable[String] = 
    items map (_.replaceAll("\\W", "")) map (_.replaceAll("\\w", "")) 

は、次のコードを考えます。私は戻り値の型が提供されたIterableのタイプに従って呼び出し元によって選択されるようにこれを一般化したいと思います。

This answer utilizing CanBuildFromは近づくが、唯一のオリジナルからの最初のmapを行います。

def trimNonWordCharacters[T <: Seq[String]] 
    (items: T with SeqLike[String, T]) 
    (implicit cbf: CanBuildFrom[T, String, T]): T = 
    items map (_.replaceAll("\\W", "")) 

第2のマップを実行する単純な行為:

def trimCharacters[T <: Seq[String]] 
    (items: T with SeqLike[String, T]) 
    (implicit cbf: CanBuildFrom[T, String, T]): T = 
    items.map(_.replaceAll("\\W", "")).map(_.replaceAll("\\w", "")) 

休憩のコンパイル:

type mismatch; 
[error] found : Seq[String] 
[error] required: T 

これをコンパイルできる変更がありますか?

答えて

1

あなたは暗黙のうちにCanBuildFromを取得しましたが、あなたはそれを採用していません。

def trimCharacters[T <: Seq[String]](items: T with SeqLike[String, T] 
            )(implicit cbf: CanBuildFrom[T, String, T] 
            ): T = { 
    val builder = cbf(items) 
    builder.sizeHint(items) 
    items.map(_.replaceAll("\\W","")).map(_.replaceAll("\\w","")).foreach(builder += _) 
    builder.result() 
} 

ところで、この場合map Sが崩壊することができます。

items.map(_.replaceAll("\\W", "").replaceAll("\\w", "")).foreach(builder += _) 
+0

私は、一般化された解が以下の通りであることを正しく理解していますか?まず、目的の結果のコレクションを得るために必要な操作をすべて行います。次に、ビルダーで '+ ='を使用してそれぞれの項目を追加して、目的の結果を反復処理します。最後に、ビルダー 'result()'によって生成された結果を返します。 – vossad01

+0

はい、私はそれが一般的な概要だと思います。いくつかの簡単な方法については、[TraversableLike source](https://github.com/scala/scala/blob/v2.12.1/src/library/scala/collection/TraversableLike.scala#L1)の方法をご覧ください。簡単な例。 – jwvh

+0

'CanBuildFrom'は、1つの操作だけが実行されるように暗黙的に使用することはできません。 – vossad01

関連する問題