gzoller/scala-reflection

Usage: retrieved erased type inside an Option

Closed this issue · 2 comments

This is not an issue, but rather a question: sorry if that's the wrong place for it.

First, this looks very interesting, thanks for sharing!

What I'd like to know is:

  1. whether I can use this library, in scala 3, to retrieve the erased type (or class rather) inside an Option at runtime? In scala 2 we were using a mix of java reflection and scalap to achieve the same thing
  2. if it's indeed possible, how is it done using this library?

I'll give an example of what I mean:

class Professor(
  val lastName: String,  
  val bossId: Option[Long]=None
) extends Table


// somewhere else

def metadata[T](table: Table[T)(implicit manifestT: ClassTag[T]: {
  val clasz = manifestT.runtimeClass.asInstanceOf[Class[T]]
  val members =  ... // use java reflection to get members i.e. clasz.getMethods

  members.map { member =>
    // here, for bossId, I know that member/field is an Option but I don't know of what Type
    // and I would like to know that it's an Option[Long]
  }
}

For more context, I am trying to port squeryl to scala 3, see this PR.

Hello.... sorry this took so long! I’ve been so focused on getting 1.0.0 out I missed this question. Yes, this library should do the trick. Reflect on Professor and you’ll get a ScalaCaseClassInfo with an array of FieldInfo. One of those will be your Option. Look at the fieldType and see the OptionInfo, and inside that is OptionParamType, which will be PrimitiveType.Scala_Long.

If the type of T is known at compile time it looks like this:

val myRtype = RType.of[Professor]

If, however, you don’t know the type until runtime you will want this:

val myRtype = RType.of(yourClazzHere)

Note that in this case you’ll really want to use the compiler plugin mode for scala_reflection as performance is terrible without it—Scala 3 limitation.

This library works in two ways. For the compile-time mode it’s unpacking the Tasty (compiler internal) structures during compilation. Runtime is much harder—Scala 3 removed reflection. Scala 2 reflection worked by serializing encoded reflection info of case classes as an annotation its runtime library could access. That’s gone in Scala 3, so my library essentially does the same thing, which is why the compiler plugin is required. Without the plugin it needs to read .tasty files using file I/O, which is clearly undesirable, but works.

Hope this helps.

thanks @gzoller for the taking the time to respond! It's good to know that it's possible to do.

I ended up solving my problem by writing a macro which must be a somewhat simplified version of your RType.of.