Scala宏:将部分函数重写为匹配
我想将Scala宏:将部分函数重写为匹配,scala,scala-macros,Scala,Scala Macros,我想将部分函数重写为匹配表达式 //macro and impl def pfRewrite(pf: PartialFunction[Int, Int]) = macro ResponderImpl.pfRewriteImpl def pfRewriteImpl(c: Context)(pf: c.Expr[PartialFunction[Int, Int]]) = { import c.universe._ val cas = pf.tree.collect { case
部分函数
重写为匹配
表达式
//macro and impl
def pfRewrite(pf: PartialFunction[Int, Int]) = macro ResponderImpl.pfRewriteImpl
def pfRewriteImpl(c: Context)(pf: c.Expr[PartialFunction[Int, Int]]) = {
import c.universe._
val cas = pf.tree.collect {
case x: DefDef if x.name.decoded == "applyOrElse" =>
x.collect {
case cq"$x => $y" => cq"""$x => $y"""
}
}.flatten
val sVal = newTermName("someVal")
val rewrite = q"""
$sVal match {
case ..$cas
}
"""
c.Expr(rewrite)
}
在代码中,我得到了一个PartialFunction
并从applyOrElse
方法中获取了一个cases
,接下来我为“someVal”创建了一个match
表达式。此值来自代码:
//test
def test {
val someVal = 10
pfRewrite {
case 1 => 10
case _ => 100
}
}
但我有错误:
[error] found : Int(10)
[error] required: Nothing
[error] case 1 => 10
[error] ^
等等
是否可以将部分函数调用重写为匹配 通常,这些令人尴尬的错误消息源于混合类型化树和非类型化树(有关更多详细信息,请参阅)。因此,在我们解决这个问题之前,最好在您计划与非类型树混合的类型树上执行resetLocalAttr 这种情况也不例外。使用
c.resetLocalAttrs(pf.tree)
而不仅仅是pf.tree
揭示了宏扩展的真正问题:
12:57 ~/Projects/Master/sandbox (master)$ scalac Test.scala
Test.scala:5: error: not found: value default
Macros.pfRewrite {
^
如果我们启用-Xprint:typer
,这是查看宏扩展的方式之一(以及-Ymacro-debug-lite
和-Ymacro-debug-verbose
),那么我们将看到发生了什么:
[[syntax trees at end of typer]] // Test.scala
package <empty> {
object Test extends AnyRef with App {
def <init>(): Test.type = {
Test.super.<init>();
()
};
def test: Unit = {
val someVal: Int = 10;
{
someVal match {
case 1 => 10
case _ => 100
case (defaultCase$ @ _) => <default: error>.apply(<x1: error>)
};
()
}
}
}
}
[[typer末尾的语法树]]///Test.scala
包装{
对象测试通过应用扩展AnyRef{
def():Test.type={
测试。超级。();
()
};
def测试:单位={
val-someVal:Int=10;
{
某些比赛{
案例1=>10
案例=100
案例(defaultCase$@)=>。应用()
};
()
}
}
}
}
看起来部分函数合成还添加了一个默认情况,我们不能按原样重用,因为它引用了在合成类中定义的一些合成变量。您能说明您期望的输出树是哪一个吗?它将用于运行时,并将
someVal
用作方法参数:def mth(s:Int)={pfRewrite{case 1=>10;case{=>100}
转换为mth(s:Int)={s匹配{…}
。或者你是什么意思?pfRewrite怎么知道它需要匹配s?还有,你试过在重写时调用resetLocalAttrs吗?@EugeneBurmako不,我没有使用resetLocalAttrs
s
是一个属性名。现在,我想重写case
块-case x:Int=>x
转换为case x:Int=>x+100
。可能还是很难?