从参数集合构造案例类

时间:2013-02-09 04:45:17

标签: scala case-class

假设:

case class Thing(a:Int, b:String, c:Double)

val v = Vector(1, "str", 7.3)

我想要一些神奇的东西:

Thing(1, "str", 7.3)

是否存在这样的事情(对于任意大小的东西)?

3 个答案:

答案 0 :(得分:3)

我第一次将脚趾浸入2.10实验反射设施中。所以大多数遵循这个大纲http://docs.scala-lang.org/overviews/reflection/overview.html,我提出了这个:

import scala.reflect.runtime.{universe=>ru}

case class Thing(a: Int, b: String, c: Double)

object Test {
  def main(args: Array[String]) {
    val v = Vector(1, "str", 7.3)
    val thing: Thing = Ref.runtimeCtor[Thing](v)
    println(thing) // prints: Thing(1,str,7.3)
  }
}

object Ref {
  def runtimeCtor[T: ru.TypeTag](args: Seq[Any]): T = {
    val typeTag = ru.typeTag[T]
    val runtimeMirror = ru.runtimeMirror(getClass.getClassLoader)

    val classSymbol = typeTag.tpe.typeSymbol.asClass
    val classMirror = runtimeMirror.reflectClass(classSymbol)

    val constructorSymbol = typeTag.tpe.declaration(ru.nme.CONSTRUCTOR).asMethod
    val constructorMirrror = classMirror.reflectConstructor(constructorSymbol)
    constructorMirrror(args: _*).asInstanceOf[T]
  }
}

请注意,当我在main方法中包含case类时,这不会编译。我不知道是否只能为非内部案例类生成类型标记。

答案 1 :(得分:1)

我不知道是否有可能得到一个有编译时错误的工作解决方案,但这是我使用匹配的解决方案:

case class Thing(a: Int, b: String, c: Double)
def printThing(t: Thing) {
  println(t.toString)
}

implicit def vectToThing(v: Vector[Any]) = v match {
  case (Vector(a: Int, b: String, c: Double)) => new Thing(a, b, c)
}

val v = Vector(1, "str", 7.3) // this is of type Vector[Any]
printThing(v) // prints Thing(1,str,7.3)
printThing(Vector(2.0, 1.0)) // this is actually a MatchError

这个“Thing”转换是否有实际目的,或者您更愿意使用Tuple3 [Int,String,Double]而不是Vector [Any]?

答案 2 :(得分:0)

从您的问题来看,目前尚不清楚您将使用它。你称之为Thing的东西实际上可能是HList或KList。 HList代表异构列表,这是一个“任意长度的元组”。

我不确定添加'unnapply'或'unapplySeq'方法会有多难,因为它的行为更像是一个案例类。

我对它们没什么经验,但可以在这里找到一个很好的解释:http://apocalisp.wordpress.com/2010/06/08/type-level-programming-in-scala/

如果这不是您所需要的,那么告诉我们您想要实现的目标可能是个好主意。