hi,
i couldn't find any Scala discussions about this (in Java-land it has been discussed aplenty, e.g. here and here), so must ask here if this has been discussed before, and if so, what the consensus was, if any:
Most Java frameworks refer to classes through java.lang.Class objects, because with the MyClass.class syntax Java directly supports compile-time-constant expressions creating Class objects. Conversely, to refer to fields or methods of a Java class, those same frameworks need to resort to using Strings, because Java does not provide compile-time-constant expressions for constructing java.lang.reflect.Field and java.lang.reflect.Method objects. For instance, in JPA/Java
@Entity
@EntityListeners(MyListener.class)
class Team {
@OneToMany(mappedBy="team")
Set<Player> players;
}
@Entity
class Player {
@ManyToOne
Team team;
}
Thus the reference to the Class object for class MyListener is checked by the compiler, while the reference to the Field object for Player::team must be simulated by the compile-time-unchecked String "team". Similar example where methods are identified by their String name abound.
Has there been a proposal for Scala to directly support syntax for constructing compile-time-constant java.lang.reflect.Field and java.lang.reflect.Method objects along the lines it currently does for java.lang.Class objects? Maybe like so:
@Entity
@EntityListeners(classOf[MyListener])
class Team {
@OneToMany(mappedBy=fieldOf[Player#team].getName)
Set<Player> players
}
and similar for methods? Thank you very much for your feedback.
cheers
gerald
Has there been a proposal for Scala to directly support syntax for constructing compile-time-constant java.lang.reflect.Field and java.lang.reflect.Method objects along the lines it currently does for java.lang.Class objects?
I don't remember writing anything down, but I've always wanted to do this. I have heard it referred to as "static reflection" and I think if we had it we'd wonder how we lived without it. I guess macros are the most plausible route right now.
If macros provide a basis for implementing this, then this feature request would be most timely ;-) Exciting!
What universes do want to pass types between?
No, something more exciting is happening. My Ints are in there, but the fact that it's a polytype is somehow making it go wrong. Why is it talking about "method apply's type parameter bounds [T]" ? Whose method apply is that?
scala> val x: ru.Type = method[List[Int]]("map")<console>:11: error: type arguments [(f: Int => B)(implicit bf: scala.collection.generic.CanBuildFrom[List[Int],B,That])That] do not conform to method apply's type parameter bounds [T]val x: ru.Type = method[List[Int]]("map")^
I guess it's somewhere in this thing of beauty:$u.AbsTypeTag.apply[(f: Int => B)(implicit bf: scala.collection.generic.CanBuildFrom[List[Int],B,That])That]($m, {final class $typecreator1 extends TypeCreator {def <init>() = {super.<init>();()};def apply[U >: Nothing <: Universe with Singleton]($m$untyped: MirrorOf[U]): U#Type = {val $u: U = $m$untyped.universe;val $m: $u.Mirror = $m$untyped.asInstanceOf[$u.Mirror];val symdef$B1 = $u.build.newNestedSymbol($u.build.selectTerm($m.staticClass("scala.collection.TraversableLike"), "map"), $u.newTypeName("B"), $u.NoPosition, $u.build.flagsFromBits(8208L), false);val symdef$That1 = $u.build.newNestedSymbol($u.build.selectTerm($m.staticClass("scala.collection.TraversableLike"), "map"), $u.newTypeName("That"), $u.NoPosition, $u.build.flagsFromBits(8208L), false);val symdef$f1 = $u.build.newNestedSymbol($u.build.selectTerm($m.staticClass("scala.collection.TraversableLike"), "map"), $u.newTermName("f"), $u.NoPosition, $u.build.flagsFromBits(8192L), false);val symdef$bf1 = $u.build.newNestedSymbol($u.build.selectTerm($m.staticClass("scala.collection.TraversableLike"), "map"), $u.newTermName("bf"), $u.NoPosition, $u.build.flagsFromBits(8704L), false);$u.build.setTypeSignature(symdef$B1, $u.TypeBounds($m.staticClass("scala.Nothing").asType.toTypeConstructor, $m.staticClass("scala.Any").asType.toTypeConstructor));$u.build.setTypeSignature(symdef$That1, $u.TypeBounds($m.staticClass("scala.Nothing").asType.toTypeConstructor, $m.staticClass("scala.Any").asType.toTypeConstructor));$u.build.setTypeSignature(symdef$f1, $u.TypeRef($u.ThisType($m.staticPackage("scala").asModule.moduleClass), $m.staticClass("scala.Function1"), scala.collection.immutable.List.apply($m.staticClass("scala.Int").asType.toTypeConstructor, $u.TypeRef($u.NoPrefix, symdef$B1, scala.collection.immutable.List.apply()))));$u.build.setTypeSignature(symdef$bf1, $u.TypeRef($u.ThisType($m.staticPackage("scala.collection.generic").asModule.moduleClass), $m.staticClass("scala.collection.generic.CanBuildFrom"), scala.collection.immutable.List.apply($u.TypeRef($u.ThisType($m.staticPackage("scala.collection.immutable").asModule.moduleClass), $m.staticClass("scala.collection.immutable.List"), scala.collection.immutable.List.apply($m.staticClass("scala.Int").asType.toTypeConstructor)), $u.TypeRef($u.NoPrefix, symdef$B1, scala.collection.immutable.List.apply()), $u.TypeRef($u.NoPrefix, symdef$That1, scala.collection.immutable.List.apply()))));$u.PolyType(scala.collection.immutable.List.apply(symdef$B1, symdef$That1), $u.MethodType(scala.collection.immutable.List.apply(symdef$f1), $u.MethodType(scala.collection.immutable.List.apply(symdef$bf1), $u.TypeRef($u.NoPrefix, symdef$That1, scala.collection.immutable.List.apply()))))}};new $typecreator1()})