Scala隐含了变量参数列表

lam*_*das 7 scala variadic-functions implicit-conversion

我有库方法采用变量参数列表和生成数据

class Data
def process(elems: String*): Data = new Data
Run Code Online (Sandbox Code Playgroud)

我希望我的字符串被隐式转换为 Data

implicit def strToData(ts: String): Data = process(t)
Run Code Online (Sandbox Code Playgroud)

所以我可以写类似的东西

val data: Data = "one"
Run Code Online (Sandbox Code Playgroud)

但是我想要隐式转换字符串元组.我添加了另一个隐含的内容

implicit def strsToData(ts: String*): Data = process(ts: _*)
Run Code Online (Sandbox Code Playgroud)

编译很好,但转换失败

val data: Data = ("one", "two")
val dat3: Data = ("one", "two", "three")
val dat4: Data = ("one", "two", "three", "four")
Run Code Online (Sandbox Code Playgroud)

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

有没有办法隐式转换元组,或者为什么可以实现它?

更新:元组可以是任何arity.

Nik*_*kov 5

  1. ts: String*不是一个元组,而是一个元组Iterable.你不能将iterable转换为元组,因为tuple是一个静态类型,它的arity在编译时被解析.Emil H回答了如何从元组进行隐式转换.
  2. 从一种类型到另一种类型的透明隐式转换是一个常见的陷阱,并且非常不鼓励.相反,您应该应用"包装器"方法,或者使用Scala 2.10以来的"值类":

    在Scala 2.9中:

    implicit def stringStringTupleExtender (ts : (String, String)) =
      new {
        def data = process(ts)
      }
    
    Run Code Online (Sandbox Code Playgroud)

    在Scala 2.10中:

    implicit class StringStringTupleExtender (val ts : (String, String)) extends AnyVal {
      def data = process(ts)
    }
    
    Run Code Online (Sandbox Code Playgroud)

    然后你会像这样使用它:

    val data : Data = ("sdf", "lsdfj").data
    val data1 : Data = "sdf".data // if you do the same for String
    
    Run Code Online (Sandbox Code Playgroud)
  3. 如果您正在寻找动态解析任何输入集合,那么,猜猜是什么,您应该使用集合,而不是元组.

    在Scala 2.9中

    implicit def seqExtender (ts : Seq[String]) =
      new {
        def data = process(ts)
      }
    
    Run Code Online (Sandbox Code Playgroud)

    用法:

    val data : Data = Seq("sdf", "lsdkfjsdl", "ldsfjk").data
    
    Run Code Online (Sandbox Code Playgroud)


Pth*_*ame 3

虽然 @NikitaVolkov 的答案中的所有警告都适用,但您可以编写一个接受任何元组数量以及任何案例类的版本:

implicit def prod2data(Product p): process((p.productIterator.toSeq):_*)
Run Code Online (Sandbox Code Playgroud)