Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala quasiquote concatenation

I'm new to scala macros and I spent a couple of days trying to write my very first one. I have a problem with quasiquotes concatenation.

There is a list of case clauses, let's say the following:

val cases = cq"x => 1 " :: cq"_ => 0 " :: Nil

And I need to build a partial function from it. The problem is that I don't have an idea how to paste them in the final quasiquote. The documentation says I should do something like this:

q"{ case ..$cases }"

but it doesn't work if I do so.

Is there a way to build a PartialFunction from such a list?

Thanks for any help.

like image 597
Natalia Grybovska Avatar asked May 20 '15 07:05

Natalia Grybovska


1 Answers

The following works for me with 2.11.2:

import scala.reflect.macros.Context
object Macros {
    def partial: PartialFunction[Int, Int] = macro partialImpl
    def partialImpl(c: Context): c.Expr[PartialFunction[Int, Int]]= {
        import c.universe._
        val cases = cq"x => 1 " :: cq"_ => 0 " :: Nil
        val pf = q"{ case ..$cases } : PartialFunction[Int, Int]"
        c.Expr[PartialFunction[Int, Int]](pf)

    }
}

Then you can call Macros.partial(1), for example, or Macros.partial.isDefinedAt(2).

Note that in order to make this work, I had to explicitly use PartialFunction[Int, Int] in the quasiquote q"{ case ..$cases } : PartialFunction[Int, Int]". It didn't work without the explicit type definition (it otherwise assumes PartialFunction[Any, Int]).

Here is the specification for quasiquote Syntax for partial functions. It works as a pure syntax tree, but apparently cannot be interpreted as a typed expression except PartialFunction[Any, T] by a macro unless the type is made explicit.

like image 197
Ben Reich Avatar answered Sep 24 '22 17:09

Ben Reich