2012-10-11 11 views
21

Mit Typ-Tags, ich bin in der Lage zu die Parameter eines bestimmten Typs zu sehen:Typ Parameter über Reflexion in Scala 2.10 zu finden?

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

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

Aber ich kann ganz einfach nicht herausfinden, wie programmatisch, dass „Int“ von dort in einem, erhalten allgemeiner Weg.

(Ich bin jetzt seit einer Stunde in REPL herumgelaufen, versuche Permutations auf Type, um zu sehen, was ich davon bekommen kann ... Ich bekomme eine Menge Dinge, die darauf hinweisen, dass es sich um eine "Liste" handelt Viel Glück bei der Suche nach diesem "Int"! Und ich möchte nicht wirklich auf die toString() Ausgabe zu analysieren ...)

Daniel Sobral hat eine ausgezeichnete (wie immer) schnellen Überblick here, in der er bekommt

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

scala> res1.typeSignatureIn(res0) 
res2: reflect.runtime.universe.Type = => Int 
: aufreizend nah an, was ich suche, aber (anscheinend) nur, wenn Sie für diese bestimmte Klasse passieren zu wissen, können einige spezifische Methode, deren Typ abgefragt werdenAber ich hoffe auf etwas Allgemeineres, was nicht bedeutet, in der Liste der deklarierten Methoden herumzuwühlen und zu hoffen, dass einer von ihnen die aktuelle Typinformation des Tags irgendwo erfassen (und somit preisgeben wird).

Wenn Scala kann so leicht Drucken "Liste [Int]", warum in aller Welt ist es so schwer zu entdecken, dass "Int" Teil davon - ohne Rückgriff auf Zeichenfolge Mustererkennung? Oder vermisse ich gerade etwas wirklich, wirklich Offensichtliches?

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

Hier ist eine Nicht-Antwort: mit M7 mindestens Sie die Typargumente durch Gießen auf eine interne bekommen API: 'typeOf [Liste [Int]]. AsInstanceOf [scala.reflect.internal.Types $ TypeApiImpl] .typeArguments'. –

+0

Clever! Vielen Dank. – Tim

Antwort

14

Leider glaube ich nicht, dass es eine Methode ist, dass Sie die Parameter geben, aber man kann von ihnen halten diese Art und Weise erhalten:

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 

bearbeiten Hier ist ein etwas schöner Weg, um die gleiche Sache (im Anschluss an eine discussion on scala-internals) zu erreichen:

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

Dies wurde auf der Mailingliste scala-internals hier diskutiert: https://groups.google.com/forum/#!msg/scala-internals/R1iZXfotqds/zqq8QjMJj74J –

+0

Das scheint es zu tun! - obwohl (Verweis auf Ihren Link) teile ich auch Ihre Unruhe! Ich möchte hier auf meine eigene Erfahrung als Argument hinweisen, warum dies gegen das Prinzip des geringsten Erstaunens verstößt. – Tim

+0

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