使用freshName作为参数而不显式指定类型



我试图在以下宏中使用freshName作为参数名称:

I

def test: Unit = macro implTst
def implTst(c: blackbox.Context): c.Expr[Unit] = {
import c.universe._
def withImplicitsM(exprs: List[c.Tree], expr: c.Tree): c.Tree =
exprs match {
case Nil =>
expr
case head :: tail =>
//error here
q"""$head.flatMap(implicit ${c.freshName()} => ${withImplicitsM(tail, expr)})"""
}
val exprsIo    = List(q"cats.effect.IO.apply(1)", q"cats.effect.IO.apply(2)")
val resultTree = q"""println(${withImplicitsM(exprsIo, q"cats.effect.IO.apply(3)")}.unsafeRunSync())"""
c.Expr[Unit](resultTree)
}

它抛出编译错误:

[error] Main.scala:25:9: exception during macro expansion: 
[error] java.lang.IllegalArgumentException: "fresh$macro$2" is not valid representation of a parameter, consider reformatting it into q"val $name: $T = $default" shape

II

用硬编码的标识符替换freshname使其工作:

def test: Unit = macro implTst
def implTst(c: blackbox.Context): c.Expr[Unit] = {
import c.universe._
def withImplicitsM(exprs: List[c.Tree], expr: c.Tree): c.Tree =
exprs match {
case Nil =>
expr
case head :: tail =>
q"""$head.flatMap(implicit i => ${withImplicitsM(tail, expr)})"""
}
val exprsIo    = List(q"cats.effect.IO.apply(1)", q"cats.effect.IO.apply(2)")
val resultTree = q"""println(${withImplicitsM(exprsIo, q"cats.effect.IO.apply(3)")}.unsafeRunSync())"""
c.Expr[Unit](resultTree)
}

有没有一种方法可以在不显式指定参数类型的情况下使用implicit ${c.freshName()}

解决方案:

在参数定义中显式使用空类型。

def withImplicitsM(exprs: List[c.Tree], expr: c.Tree): c.Tree =
exprs match {
case Nil =>
expr
case head :: tail =>
val emptyType = tq""
val v         = q"implicit val ${TermName(c.freshName())}: $emptyType"
q"""$head.flatMap($v => ${withImplicitsM(tail, expr)})"""
}

我是怎么想出来的

我破坏了一个类似的flatMap调用,并查看了参数定义的样子:

val flatmapExpression               = q"cats.effect.IO.apply(1).flatMap(implicit i => cats.effect.IO.apply(2))"
val q"$foo($args)"                  = flatmapExpression
val q"(..$params) => $body"         = args
val q"$mods val $name: $tpt = $rhs" = params(0)
println(mods)
println(name)
println(tpt)
println(rhs)

以下是打印出来的内容:

Modifiers(implicit <param>, , Map())
i
<type ?>
<empty>

注意作为空类型的CCD_ 3。

相关内容

  • 没有找到相关文章

最新更新