1

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!

6
  • 1
    Can't write it but I think looking at LabelledGeneric implementation could help. Commented Mar 23, 2020 at 13:32
  • 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? Commented Mar 23, 2020 at 13:38
  • 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. Commented Mar 23, 2020 at 13:47
  • val currentPrice = rec(`price) should work. Commented Mar 23, 2020 at 23:08
  • 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? Commented Mar 24, 2020 at 15:04

1 Answer 1

1

Try

import shapeless.LabelledGeneric
import shapeless.record._
LabelledGeneric[MyPersonalCaseClass].to(someVariable).get(Symbol("token")) // 123
Sign up to request clarification or add additional context in comments.

2 Comments

This is ok. Got another similar solution on the same line. This solution has the positive effect of checking the type at compile time, even if the IDE does not complain initially. If i let the IDE suggest the type it returns type :Nothing. I have no evidence it is possible to do better than something like this.
@nicolaosc Sorry but IDE suggestion is irrelevant. Question about IDE is not question about Scala.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.