考虑以下类型:
sealed trait PosIntCheckResult
case class LteZero(x: Int) extends PosIntCheckResult
case object NotConstant extends PosIntCheckResult
我正在尝试编写一个宏来检查给定的Int
是否大于0。
import reflect.macros.Context
def getInt(c: Context)(value: c.Expr[Int]): Either[PosIntCheckResult, Int] = {
import c.universe._
value.tree match {
case Literal(Constant(x)) => if (x > 0) Right(x) else Left(LteZero(x))
case _ => Left(NotConstant)
}
}
但Any
显示x
值:
Test.scala:29: type mismatch;
found : Any
required: Int
case Literal(Constant(x)) =>
if (x > 0) Right(x) else Left(LteZero(x))
如何让编译器期望Int
而不是Any
?
答案 0 :(得分:1)
您必须匹配x
为Int
的模式:
case Literal(Constant(x: Int)) => //When using x here, it is an Int
在docs中阅读关于类型的模式匹配和其他类型的模式匹配。
您还应注意,您的宏需要返回Expr
才能正常工作。您可以使用reify
在每个Exprs
构建所需的case
。阅读reify
和def macros
here。我不确定为什么这需要成为一个宏,但如果你只是学习这些技术,这样的东西可能有用:
object Macros {
def getInt(value: Int): Either[PosIntCheckResult, Int] = macro getIntImpl
def getIntImpl(c: Context)(value: c.Expr[Int]): c.Expr[Either[PosIntCheckResult,Int]] = {
import c.universe._
value.tree match {
case x@Literal(Constant(const: Int)) if const > 0 => reify(Right(c.Expr[Int](x).splice))
case x@Literal(Constant(_: Int)) => reify(Left(LteZero(c.Expr[Int](x).splice)))
case _ => reify(Left(NotConstant))
}
}
}