How to build a dynamic sequence in a scala macro?

爱⌒轻易说出口 提交于 2019-12-04 09:48:17

You can provide a type parameter to reify to avoid the casts. Turning the sequence of expressions inside out is a little trickier, but not much:

case class Foo(name: String)
case class Bar(foo: Foo)
case class Baz(foos: Seq[Foo])

import scala.language.experimental.macros
import scala.reflect.macros.Context

def demo: Baz = macro demo_impl
def demo_impl(c: Context) = {
  import c.universe._

  def foo(name: String) = reify[Foo](Foo(c.literal(name).splice))
  def bar(foo: Expr[Foo]) = reify[Bar](Bar(foo.splice))

  def baz(foos: Seq[Expr[Foo]]): Expr[Baz] = {
    val flipped: Expr[Seq[Foo]] = c.Expr[Seq[Foo]](
      Apply(
        Select(reify(Seq).tree, newTermName("apply")),
        foos.map(_.tree).toList
      )
    )

    reify(Baz(flipped.splice))
  }

  baz(Seq(foo("MyFoo1"), foo("MyFoo2")))
}

Life is so much better in paradise, though:

def demo: Baz = macro demo_impl
def demo_impl(c: Context) = {
  import c.universe._

  def foo(name: String) = c.Expr(q"Foo($name)")
  def bar(foo: Expr[Foo]) = c.Expr(q"Bar($foo)")
  def baz(foos: Seq[Expr[Foo]]) = c.Expr(q"Baz(Seq(..$foos))")

  baz(Seq(foo("MyFoo1"), foo("MyFoo2")))
}

This is exactly equivalent to the first implementation, but uses quasiquotes—which are now available in 2.10 as a compiler plugin—instead of reification and manual tree construction.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!