【问题标题】:How do I combine Type Programming with Scala Macros如何将类型编程与 Scala 宏结合起来
【发布时间】:2013-05-08 10:03:12
【问题描述】:

我想使用一个使用“type”关键字定义的类型的宏。如何引用?

我的起始码是

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

trait Demo6 {
  type T

  def add(param: Any): T = macro Demo6.addImpl[T]

  def fullAdd(param: Any, toStringBasedOnAST: String): T = {
    doesSomeThing_and_returnsSomething_OfTypeT
  }
  def doesSomeThing_and_returnsSomething_OfTypeT: T //just to allow compilation
}

object Demo6 {
  def addImpl[T: c.WeakTypeTag](c: Context)(param: c.Expr[Any]): c.Expr[T] = {
    import c.universe._
    reify { (c.Expr[Demo6](c.prefix.tree)).splice.fullAdd(param.splice, 
                                        c.literal(show(param.tree)).splice) }
    //        ^ - type mismatch; found : org.autotdd.scalamacros.Demo6#T 
    //                           required: T
  }
}

我已经在示例中标记了编译器错误。很清楚发生了什么:关键字定义的类型 T 与我传入的类型 T 不同。

我尝试过的事情 scala-macros 上还没有很多文档。 http://docs.scala-lang.org/overviews/macros/overview.html 中的部分非常有帮助,但它的示例使用了类级别和方法级别的泛型。我浏览了 Expecty 和 macrocosm 的代码,它们是文档中引用的项目,但找不到这样的代码。

【问题讨论】:

  • T需要使用type标签吗?如果没有,你甚至不需要addImplT 参数——你应该可以使用TypedTypeName("T")

标签: scala scala-macros


【解决方案1】:

您的代码几乎是正确的,只需更改Expr的类型参数:

val expr = reify { ... }
c.Expr[T](expr.tree)

没有reify,你应该返回这个:

c.Expr[T](Apply(Select(c.prefix.tree, newTermName("fullAdd")),
                List(param.tree, Literal(Constant(show(param.tree))))))

reify 创建相同,但类型参数错误。

请参阅 this answer 了解 showRaw 的用法。

在这种情况下:

scala> import reflect.runtime.universe._
import reflect.runtime.universe._

scala> {
     |   object Demo { def fullAdd(param1: Any, param2: String): String = "result" }
     |   showRaw{ reify { Demo.fullAdd("param1", "param2") } }
     | }
res0: String = Expr(Apply(Select(Ident(newTermName("Demo")), newTermName("fullAdd")), List(Literal(Constant("param1")), Literal(Constant("param2")))))

Ident(newTermName("Demo")) 替换为c.prefix.tree,将Literal(Constant("param1")) 替换为param.tree,将"param2" 替换为show(param.tree),您将得到结果。

【讨论】:

  • 谢谢:真的很好用。我正在努力理解你是如何解决这个问题的。你能建议任何可以帮助我的代码吗?
  • 这是一个非常好的链接,谢谢。我可以看到我花了几个小时阅读它:)
猜你喜欢
  • 2015-08-03
  • 2011-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-22
相关资源
最近更新 更多