scala reflection toolbox scala-2.10

Generar una clase a partir de cadenas y crear instancias en Scala 2.10



reflection toolbox (1)

En Scala 2.10, ¿cómo puedo generar una clase a partir de una cadena (probablemente, usando la API de Toolbox) para crear una instancia con la reflexión de Scala?


Las cajas de herramientas de compilación de Wrt solo pueden ejecutar expresiones = valores de retorno, pero no clases resultantes o conjuntos de archivos / bytes con resultados de compilación.

Sin embargo, aún es posible lograr lo que desea, ya que en Scala es tan fácil pasar del nivel de tipo al nivel de valor utilizando valores implícitos:

Editar . En 2.10.0-RC1 algunos métodos de ToolBox han sido renombrados. parseExpr ahora se acaba de parse , y runExpr ahora se llama eval .

scala> import scala.reflect.runtime._ // requires scala-reflect.jar // in REPL it''s implicitly added // to the classpath // but in your programs // you need to do this on your own import scala.reflect.runtime scala> val cm = universe.runtimeMirror(getClass.getClassLoader) cm @ 41d0fe80: reflect.runtime.universe.Mirror = JavaMirror with scala.tools.nsc.interpreter.IMain$TranslatingClassLoader... scala> import scala.tools.reflect.ToolBox // requires scala-compiler.jar // in REPL it''s implicitly added // to the classpath // but in your programs // you need to do this on your own import scala.tools.reflect.ToolBox scala> val tb = cm.mkToolBox() tb: scala.tools.reflect.ToolBox[reflect.runtime.universe.type] = scala.tools.reflect.ToolBoxFactory$ToolBoxImpl@3a962da5 scala> tb.runExpr(tb.parseExpr("class C; scala.reflect.classTag[C].runtimeClass")) res2: Any = class __wrapper$1$f9d572ca0d884bca9333e251c64e980d$C$1

Actualización # 1. Si no necesita una java.lang.Class y solo necesita crear una instancia de la clase compilada, puede escribir una new C directamente en la cadena enviada a runExpr .

Actualización # 2. También es posible hacer que runExpr use la asignación personalizada de nombres de variables a valores de tiempo de ejecución. Por ejemplo:

scala> val build = scala.reflect.runtime.universe.build build: reflect.runtime.universe.BuildApi = scala.reflect.internal.BuildUtils$BuildImpl@50d5afff scala> val x = build.setTypeSignature(build.newFreeTerm("x", 2), typeOf[Int]) x: reflect.runtime.universe.FreeTermSymbol = free term x scala> tb.runExpr(Apply(Select(Ident(x), newTermName("$plus")), List(Literal(Constant(2))))) res0: Any = 4

En este ejemplo, creo un término libre que tiene un valor de 2 (el valor no tiene que ser un primitivo, puede ser su objeto personalizado) y le asigna un identificador. Este valor se usa tal cual en el código que se compila y ejecuta con una caja de herramientas.

El ejemplo usa el ensamblaje AST manual, pero es posible escribir una función que analiza una cadena, busca identificadores independientes, busca valores para ellos en algún mapeo y luego crea los términos libres correspondientes. Sin embargo, no existe tal función en Scala 2.10.0.