Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use reflection at compile time

I have this situation:

class Column {
}

trait Table {
    lazy val columns: List[Column] = ....
}

class MyTable extends Table {
   val column1 = new Column()
   val column2 = new Column()
}

I would like to get the list of columns defined in derived classes at compile time.

I've already been able to do by using runtime reflection, but I've heard that it can be problematic in Android and ProGuard. So, I'd like to do it at compile time if possible.

https://groups.google.com/forum/#!topic/scala-on-android/Q0E_OMYqE0A

Here is my implementation with runtime reflection:

trait Table {
    lazy val columns: List[Column] = {
        import scala.reflect.runtime.universe._
        val rm = scala.reflect.runtime.currentMirror
        val columns = rm.classSymbol(this.getClass).toType.members.collect {
            case m: MethodSymbol if m.isGetter && m.returnType <:< typeOf[Column] => m
        }
        val espejo = rm.reflect(this)
        (for (col <- columns) yield
            espejo.reflectMethod(col).apply().asInstanceOf[Column]).toList
    }    
}
like image 604
david.perez Avatar asked Nov 01 '22 23:11

david.perez


1 Answers

You could do this with a Scala "def macro2 in Scala 2.10 and higher. A def macro is essentially a function that will get called during compilation with the AST (abstract syntax tree) of the parameters given to the function, that function will then also return an AST that the compiler will put in place of the call to the macro.

You can read more about it here: http://docs.scala-lang.org/overviews/macros/overview.html

like image 175
johanandren Avatar answered Nov 15 '22 06:11

johanandren