Czy istnieje sposób na uzyskanie nazw parametrów danego konstruktora za pomocą scala-macros?Jak uzyskać nazwy argumentów konstruktora za pomocą Scala-Makra?
Dzięki
Czy istnieje sposób na uzyskanie nazw parametrów danego konstruktora za pomocą scala-macros?Jak uzyskać nazwy argumentów konstruktora za pomocą Scala-Makra?
Dzięki
Należy zauważyć, że podejście :power
w odpowiedzi Paul Butcher daje Ci dostęp do API wewnętrznych, co chyba nie jest ani konieczne, lub pożądane, jeśli próbujesz to zrobić w makrze (lub w środowisku wykonawczym odbicie poza REPL, o to chodzi).
Tak na przykład dzwoniąc isConstructor
na zwykłym starym Symbol
dostarczonych przez members
w publicznym Reflection API nie będzie działać, trzeba najpierw upewnić się, że masz MethodSymbol
. Podobnie z tpe
. Można oczywiście rzutować na wewnętrzne API w kodzie innym niż REPL, ale jest to niebezpieczne i niepotrzebne. Poniżej znajduje się lepszym rozwiązaniem:
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))
}
Lub po prostu:
typeOf[Foo].declarations.collect {
case m: MethodSymbol if m.isConstructor => m.paramss.map(_.map(_.name))
}
Oba daje następujące:
List(List(List(name, i)), List(List(name)))
zgodnie z zapotrzebowaniem. Użyłem tutaj refleksji runtime, aby uprościć przykład, ale to będzie działać dokładnie tak samo z Universe
, które otrzymasz ze swojego Context
w makrze.
Ten REPL zapis powinien być ci, mam nadzieję:
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)
Jak mogę sprawić, aby działał w klasie scala podczas kompilacji? –
Ah - dobry punkt dotyczący: trybu zasilania. Dzięki za uratowanie moich rumieńców! –