Gibt es eine Möglichkeit, Parameternamen eines gegebenen Konstruktors mit Hilfe von Scala-Makros zu erhalten?Wie bekomme ich Konstruktorargumente mit Scala-Makros?
Dank
Gibt es eine Möglichkeit, Parameternamen eines gegebenen Konstruktors mit Hilfe von Scala-Makros zu erhalten?Wie bekomme ich Konstruktorargumente mit Scala-Makros?
Dank
Beachten Sie, dass die :power
Ansatz in Paul Butcher Antwort gibt Ihnen Zugriff auf interne APIs, die wahrscheinlich auch nicht notwendig ist, oder gewünscht, wenn Sie dies in einem Makro (oder in der Laufzeitreflexion außerhalb der REPL) tun wollen.
So zum Beispiel isConstructor
auf einer einfachen alten Symbol
von members
im öffentlichen Reflection-API zur Verfügung gestellt Aufruf wird nicht funktionieren-Sie zuerst sicherstellen müssen, dass Sie ein MethodSymbol
haben. Ähnlich mit tpe
. Sie könnten natürlich die internen APIs in Nicht-REPL-Code umwandeln, aber das ist gefährlich und unnötig. Hier finden Sie eine bessere Lösung:
import scala.reflect.runtime.universe._
class Foo(name: String, i: Int) { def this(name: String) = this(name, 0) }
typeOf[Foo].declaration(nme.CONSTRUCTOR).asTerm.alternatives.collect {
case m: MethodSymbol => m.paramss.map(_.map(_.name))
}
Oder einfach:
typeOf[Foo].declarations.collect {
case m: MethodSymbol if m.isConstructor => m.paramss.map(_.map(_.name))
}
Beide geben Ihnen die folgenden:
List(List(List(name, i)), List(List(name)))
nach Wunsch. Ich habe Laufzeit-Reflektion hier verwendet, um das Beispiel zu vereinfachen, aber das wird genau so funktionieren mit der Universe
, die Sie von Ihrem Context
in einem Makro erhalten.
Dieses REPL Transkript sollte, hoffe ich loslegen:
Welcome to Scala version 2.10.0-RC5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_09).
Type in expressions to have them evaluated.
Type :help for more information.
scala> :power
** Power User mode enabled - BEEP WHIR GYVE **
** :phase has been set to 'typer'. **
** scala.tools.nsc._ has been imported **
** global._, definitions._ also imported **
** Try :help, :vals, power.<tab> **
scala> class Foo(x: Int, y: Float)
defined class Foo
scala> (typeOf[Foo].members find (_.isConstructor)).get.tpe.params map (_.name)
res1: List[$r.intp.global.Symbol#NameType] = List(x, y)
Wie kann ich es in der Scala-Klasse in Kompilierzeit arbeiten lassen? –
Ah - ein guter Punkt über: Power-Modus. Danke, dass du meine Erröten gerettet hast! –