2017-05-16 8 views
0

私は単純な暗黙の関数を書いています:mkString()のバージョンは同じですが、結合されている引数のいずれかに区切りが見つかるとエラーを投げます。私はそれがすべてのシーケンスのような物事を動作させるためにしたいので、次のように私はそれを宣言した:Scala 2.10 TraversableOnce上の暗黙の関数は配列を受け入れるべきですが、

object SafeMkString { 
    implicit class SafeMkStringHelper[T](values: TraversableOnce[T]) { 
    def safeMkString(sep: String) = { 
     values.map { v => 
     val asStr = v.toString 
     if (asStr.contains(sep)) 
      throw new IllegalArgumentException("Value %s in %s contains separator %s" format 
      (asStr, values, sep)) 
     else 
      asStr 
     }.mkString(sep) 
    } 
    } 
} 

これは、ほとんどのオブジェクトのために正常に動作しますが、タイプArray[String]の何かをScalaの2.10に失敗します。これは、Scalaの配列は単純にJava配列のエイリアスであり、TraversableOnceから継承しないためです。ただし、ArrayからWrappedArrayへの暗黙的な変換は、を継承します。TraversableOnceを継承しています。 Scalaでは、A→BからB→Cへの暗黙的な変換を禁止する規則がいくつかありますか?明示的に適用する別の暗黙的なクラスを手作業で作成する以外に、Array[T]からsafeMkStringを取得する方法がありますか?あなたの第一の質問への答えで

答えて

3

、これはProgramming in Scala (1st Edition)からである、第21章:

1つずつルール:一つだけの暗黙のが試されます。コンパイラは、x + yをconvert1(convert2(x))+ yに書き換えることはありません。そうすることで、誤ったコードでコンパイル時間が劇的に増加し、プログラマーが書いたものとプログラムが実際に何を書いているかの違いが大きくなります。まあ、暗黙のうちに、別の暗黙的な関数を試す途中であれば、コンパイラは暗黙の変換を挿入しません。しかし、暗黙的なパラメータを取ることによってこの制限を回避することは可能です。これについては、この章の後半で説明します。 @jwvh答え(引用の特に最後の行)に触発され

+0

Doh、本当にRTFMのケースです。 –

2

、私は以下を思い付いた:

何それがないことがある任意のタイプ Aから暗黙的な変換を与えている
implicit class CanBeTraversable[A, T](a: A)(implicit ev: A => TraversableOnce[T]){ 
    def safeMkString(sep: String) = { 
    val values = ev(a) 
    ... //put here the body of your method 
} 

いくつかのTについて暗黙的にTraversableOnce[T]に変換されます。 Listの場合は、=:= : List[T] => List[T]は暗黙の変換であるため(Function1は第2パラメータの共変であるため、Function1[List[T], List[T]] <: Function1[List[T], TraversableOnce[T]]です)暗黙の変換がWrappedArrayになっているため、Arrayでも動作します。

関連する問題