Something to underline in Seth’s latter example: AFAIK, <:< is mainly used in type signatures, to prove that a type relationship is correct at compile time. I hadn’t even realized it could be used at runtime…
Thanks for the link. I think that’ll be useful. Is the reflection API something that is maintained from release to release? The document is marked as EXPERIMENTAL.
It will remain experimental for the lifetime of Scala 2.
It’s highly unlikely that the reflection API will undergo any really substantial changes in any future 2.x releases, but smaller changes (including breaking ones) remain possible.
Hi Dmytro, can you elaborate about how this is supposed to work?
Is it the intent that getType returns Any ? and getClass returns the most specific class?
Here is the simple code I’m using in the scala worksheet
import scala.reflect.runtime.universe._
def getType[A: TypeTag](a: A): Type = typeOf[A]
val data = List(1,2.0,"three")
data.map(_.getClass)
data.map(getType)
And here is the output from the worksheet.
import scala.reflect.runtime.universe._
def getType[A](a: A)(implicit evidence$1: reflect.runtime.universe.TypeTag[A]): reflect.runtime.universe.Type
val data: List[Any] = List(1, 2.0, three)
val res0: List[Class[_]] = List(class java.lang.Integer, class java.lang.Double, class java.lang.String)
val res2: List[reflect.runtime.universe.Type] = List(Any, Any, Any)
That output is as-expected, because Type and TypeTag represent compile-time types, but as soon as you List(1,2.0,"three"), you’ve told the compiler to throw away its compile-time knowledge of the types of the individual items and just treat all of them as Anys.
If you look at Dmytro’s original post, he already said so:
Notice that data has type List[Any] so both c1 and c2 are Any
What is it that you’re actually trying to accomplish?
I’m trying to understand what dynamic type information is available on data which the compiler thinks is Any. What information can be attained at runtime even if the compiler doesn’t know much information about the types.
Answer 1: The question suggests confused thinking. What are you trying to accomplish?
Answer 2: Yes:
scala 2.13.3> class C; val x: Any = new C
class C
val x: Any = C@6740a11c
scala 2.13.3> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala 2.13.3> val mirror = runtimeMirror(getClass.getClassLoader)
val mirror: reflect.runtime.universe.Mirror = ...
scala 2.13.3> mirror.classSymbol(x.getClass).toType
val res0: reflect.runtime.universe.Type = C
Taking a look at the blog post, it is a bit confusing.
In the section * No values, infinite types: method type parameters* the author seems to reach an invalid conclusion from this though experiment. He says assume you can list all the classes in your class path, then reaches a conclusion from which he concludes that G is not a class. That’s a wrong conclusion. Isn’t it? It could also mean that the set of classes is uncountable.
I would guess that the set of types is uncountable, at least it is in the type systems I know more about.
But, in runtime, you can ask for the list of all classes and that would be finite.
However, in compile time, you can not ask for the list of all types; since it is infinite.
Seth, I’m not sure if you’re really interesting in knowing the details of what I’m trying to accomplish. I’m happy to answer, but I don’t want to bore or burden you excessively.
I’m mainly trying to understand what dynamic capability Scala presents to the programming. When I have a heterogeneous collection of objects, what kind of type/class queries I can do at run-time. I.e., can I search for particular type patterns in such data.
To which extent does the runtime type/class reflection interface differ from that of clojure which is implemented atop the same JVM.
The ultimate goal is to try to describe how much of this type of dynamic type checking can be done in Scala and Clojure atop the Java type system.