Typesafe macro to extract value of case class field

We have been banging our heads for a while on this but we cannot find a solution.
In our project we would like to write some DSL to migrate some old code in our codebase.

We would like to make a macro that given an instance of a case class gives us the possibility to extract the value in a typesafe manner. In this case it should be possible to declare x of type Int.

val someVariable = MyPersonalCaseClass(123, "SOMESTRING")
val x = Macros.->(someVariable, "token")
def ->[T](value:T,key: String): Any = macro MacrosImpl.arrow[T]

We assumed that the only way was with whitebox macros, feel free to change the signatures.

def arrow[T: c.WeakTypeTag](c: whitebox.Context)(value: c.Expr[T], key:c.Expr[String]): c.Expr[Any] = {
    import c.universe._
    val caseClassType: c.universe.Type = weakTypeOf[T]
    ???
  }

Scala version is “2.12.8”.

thanks in advance!

Just to make sure I understand what you’re looking for:

val someVariable = MyPersonalCaseClass(123, "SOMESTRING")
val x = Macros.->(someVariable, "token")

This is for a structure like this?

case class MyPersonalCaseClass(token: Int, str: String)

More importantly, “token” is a compile-time constant, referring to the field name, correct? (More on this below.)

Assuming that it’s correct – do you have a specific reason why you want to write your own macro? Similar functionality to this is available out of the box using a lens library like Monocle, and you could certainly build this and far more using Shapeless. Both are probably easier than rolling your own macro.

If the string “token” isn’t a compile-time constant, though, this is pretty obviously impossible – if the field name isn’t known at compile-time, then there is no way to know at compile-time what type it resolves to.

It might be easier to give a good answer if you can explain the intended use case…

1 Like

Correct, the programmer will be referring to a field name of the case class. If it is not a valid name it is correct for the compiler to complain.

The reason is we are porting a lot of code from perl and we would like to give the programmers a vagueish idea they are still writing it :wink:

I am aware of their existance, if you could point me out some examples with this use-case it would be great!

Ideally we would like to make a DSL to let the users keep writing someHash->"token" but alot of operators are reserved so we can settle for less :slight_smile:

If "token" is a compile time constant, what is different from just.

val x = someVariable.token

I do not understand what do you win in this case.

2 Likes

The difference is the existing “programmers” user-experience. They have a lot of experience with Perl language but they are not programmers. Retraining them would cost a lot more than getting some simple macros.