Дано:
case class Thing(a:Int, b:String, c:Double)
val v = Vector(1, "str", 7.3)
Я хочу что-то, что будет волшебным образом создавать:
Thing(1, "str", 7.3)
Существует ли такая вещь (для Вещей произвольного размера)?
Дано:
case class Thing(a:Int, b:String, c:Double)
val v = Vector(1, "str", 7.3)
Я хочу что-то, что будет волшебным образом создавать:
Thing(1, "str", 7.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]
}
}
Обратите внимание, что когда у меня был класс case внутри основного метода, он не компилировался. Я не знаю, могут ли теги типов создаваться только для классов, не являющихся внутренними.
Я не знаю, возможно ли получить рабочее решение с ошибкой времени компиляции, но это мое решение с использованием сопоставления:
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
Есть ли реальная цель этого преобразования «Вещь» или вы бы предпочли использовать Tuple3[Int,String,Double] вместо Vector[Any]?
Из вашего вопроса неясно, для чего вы будете его использовать. То, что вы называете вещью, на самом деле может быть HList или KList. HList означает Гетерогенные списки, которые представляют собой кортежи произвольной длины.
Я не уверен, насколько сложно было бы добавить метод unnapply или unapplySeq, чтобы он вел себя как класс case.
У меня мало опыта работы с ними, но хорошее объяснение можно найти здесь: http://apocalisp.wordpress.com/2010/06/08/type-level-programming-in-scala/
Если это не то, что вам нужно, было бы неплохо сообщить нам, чего вы хотите достичь.
library.construct[CaseClassType]("one" :: 1 :: true :: Nil)
?
- person EECOLOR; 09.02.2013
Seq[Any]
, а как что-то похожее на кортеж, то вам не нужно писать свой собственный HList. Вы можете использовать github.com/milessabin/shapeless.
- person huynhjl; 09.02.2013