7

可変引数リストを取得してデータを生成するライブラリメソッドがあります

class Data
def process(elems: String*): Data = new Data

文字列を暗黙的に次のように変換したいData

implicit def strToData(ts: String): Data = process(t)

だから私は次のようなものを書くことができます

val data: Data = "one"

しかし、文字列のタプルも暗黙的に変換されるようにしたいです。別の暗黙のを追加しました

implicit def strsToData(ts: String*): Data = process(ts: _*)

正常にコンパイルされますが、変換は失敗します

val data: Data = ("one", "two")
val dat3: Data = ("one", "two", "three")
val dat4: Data = ("one", "two", "three", "four")

found   : Seq[java.lang.String]
required: this.Data
val data: Data = Seq("one", "two")

タプルを暗黙的に変換する方法、またはそれを実現できる理由はありますか?

更新:タプルは任意のアリティにすることができます。

4

3 に答える 3

5
  1. ts: String*タプルではなく、Iterable. タプルは静的な型であり、そのアリティはコンパイル時に解決されるため、イテラブルをタプルに変換することはできません。Emil H は、タプルから暗黙的な変換を行う方法に答えました。
  2. ある型から別の型への透過的な暗黙的な変換はよくある落とし穴であり、できるだけお勧めしません。代わりに、「ラッパー」アプローチを適用するか、Scala 2.10 以降の「値クラス」を使用する必要があります。

    Scala 2.9 では:

    implicit def stringStringTupleExtender (ts : (String, String)) =
      new {
        def data = process(ts)
      }
    

    Scala 2.10 では:

    implicit class StringStringTupleExtender (val ts : (String, String)) extends AnyVal {
      def data = process(ts)
    }
    

    次に、次のように使用します。

    val data : Data = ("sdf", "lsdfj").data
    val data1 : Data = "sdf".data // if you do the same for String
    
  3. 入力コレクションを動的に解決することを探している場合は、タプルではなくコレクションを使用する必要があると思います。

    Scala 2.9 では

    implicit def seqExtender (ts : Seq[String]) =
      new {
        def data = process(ts)
      }
    

    使用法:

    val data : Data = Seq("sdf", "lsdkfjsdl", "ldsfjk").data
    
于 2012-07-27T11:14:53.280 に答える
3

@NikitaVolkovの回答のすべての警告は二重に適用されますが、タプルの任意のアリティと任意のケースクラスを受け入れるバージョンを作成できます。

implicit def prod2data(Product p): process((p.productIterator.toSeq):_*)
于 2012-07-27T15:11:27.827 に答える
2

タプルから への暗黙的な変換を作成する必要がありますData

implicit def strTplToData(ts:(String, String)) = process(ts._1, ts._2)

次に、次のことができます。

val data: Data = ("one", "two")
于 2012-07-27T10:48:01.230 に答える