1
votes

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.

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

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

Here “token” is a compile-time constant, referring to the field name. The macro can be declared with something like

def ->[T](value:T,key: String): Any = macro MacrosImpl.arrow[T]

As for our understanding 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”.

The reason we need something like this 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.

thanks in advance!

1
Can't write it but I think looking at LabelledGeneric implementation could help.Alexey Romanov
The simple use of that library and this class would help indeed. val currentPrice = rec(Symbol("price")) // Static type is Double Would it be possible to write some template to get rid of the Symbol(" part?nicolaosc
I expect it's possible, by writing a macro which expands to the version with Symbol. But I won't be able to help with it at the moment.Alexey Romanov
val currentPrice = rec(`price) should work.Levi Ramsey
intellij is not very happy with val currentPrice = rec(price)` but it works. No type-safety though, cannot assign Int to the variable currentPrice. More precisely, any type works for the IDE. Tried also to import the whole scala file linked with LabelledGeneric and also in that i do not have type-safety. val currentPrice = rec(Symbol("price")) // Static type is Double maybe I am misunderstanding the comment here?nicolaosc

1 Answers

1
votes

Try

import shapeless.LabelledGeneric
import shapeless.record._
LabelledGeneric[MyPersonalCaseClass].to(someVariable).get(Symbol("token")) // 123