2012-10-11 53 views
21

El uso de etiquetas de tipo, yo soy capaz de ver los parámetros de algún tipo:¿Encontrar parámetros de tipo por reflejo en Scala 2.10?

scala> import scala.reflect.runtime.universe._ 
import scala.reflect.runtime.universe._ 

scala> typeOf[List[Int]] 
res0: reflect.runtime.universe.Type = List[Int] 

Pero simplemente no puedo encontrar la manera de obtener mediante programación que "Int" fuera de allí, en una manera general

(He estado deambulando por REPL durante una hora, probando permutaciones en Type, para ver qué puedo obtener de él ... Recibo muchas cosas que indican que esto es una "Lista", pero ¡buena suerte al encontrar ese "Int"! Y realmente no quiero recurrir al análisis de la salida toString() ...

Daniel Sobral tiene una excelente (rápida) descripción general rápida here, en la que obtiene tentadoramente cerca de lo que estoy buscando, pero (aparentemente) sólo si por casualidad usted conoce, por esa clase en particular, algún método específico cuyo tipo puede ser interrogado:

scala> res0.member(newTermName("head")) 
res1: reflect.runtime.universe.Symbol = method head 

scala> res1.typeSignatureIn(res0) 
res2: reflect.runtime.universe.Type = => Int 

Pero espero algo más general, que no implique rootear la lista de métodos declarados y esperar que uno de ellos capture (y divulgue) la información del tipo actual de la etiqueta en alguna parte.

Si Scala puede tan fácilmente imprimir "Lista [Int]", ¿por qué es tan difícil descubrir esa parte "Int" de eso, sin recurrir a la coincidencia de patrón de cadena? ¿O simplemente me estoy perdiendo algo realmente obvio?

scala> res0.typeSymbol.asInstanceOf[ClassSymbol].typeParams 
res12: List[reflect.runtime.universe.Symbol] = List(type A) 

scala> res12.head.typeSignatureIn(res0) 
res13: reflect.runtime.universe.Type = 

Grr ...

+0

Aquí hay una no-respuesta: con M7, al menos, puede obtener los argumentos de tipo echando a un interno API: 'typeOf [List [Int]]. AsInstanceOf [scala.reflect.internal.Types $ TypeApiImpl] .typeArguments'. –

+0

¡listo! Gracias. – Tim

Respuesta

14

Por desgracia, no creo que hay un método que le dará los parámetros, pero se puede conseguir de ellos de esta manera:

Welcome to Scala version 2.10.0-20121007-145615-65a321c63e (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_35). 
Type in expressions to have them evaluated. 
Type :help for more information. 

scala> import scala.reflect.runtime.universe._ 
import scala.reflect.runtime.universe._ 

scala> typeOf[List[Int]] 
res0: reflect.runtime.universe.Type = scala.List[Int] 

scala> res0 match { case TypeRef(_, _, args) => args } 
res1: List[reflect.runtime.universe.Type] = List(Int) 

scala> res1.head 
res2: reflect.runtime.universe.Type = Int 

Editar Aquí está una manera un poco más bonitas de lograr lo mismo (después de una discussion on scala-internals):

scala> res0.asInstanceOf[TypeRefApi].args 
res1: List[reflect.runtime.universe.Type] = List(Int) 
+0

Esto se discutió en la lista de distribución de scala-internals aquí: https://groups.google.com/forum/#!msg/scala-internals/R1iZXfotqds/zqq8QjMJj74J –

+0

¡Parece que lo hace! - aunque (haciendo referencia a su enlace) ¡comparto su inquietud también! Diría mi propia experiencia aquí como un argumento de por qué esto viola el principio de menos asombro. – Tim

+0

https://groups.google.com/d/topic/scala-internals/56KRF98Mdjo/discussion –

Cuestiones relacionadas