def foo(data: Option[Int]): Unit =
if (data.forall(_ > 50)) println("OK")
else println("KO")
foo(None)
// => OK
foo(Some(1))
// => KO
foo(Some(51))
// OK
data match {
case None => doSomething()
case Some(data) if data > 50 => doSomething()
case _ => doOther()
}
如果这种组合(None || Some(data) && data > 50)经常发生,您可以引入定制的提取程序
object GreaterThan50OrEmpty {
def unapply(arg: Option[Int]): Boolean = arg match {
case None => true
case Some(data) if data > 50 => true
case _ => false
}
}
data match {
case GreaterThan50OrEmpty() => println("matches pattern")
case _ => println("default")
}
你甚至可以随意叫它
object `None || Some(data) && data > 50` {
def unapply(arg: Option[Int]): Boolean = arg match {
case None => true
case Some(data) if data > 50 => true
case _ => false
}
}
data match {
case `None || Some(data) && data > 50`() => println("matches pattern")
case _ => println("default")
}
稍微笼统一点的方法
class GreaterThanOrEmpty(dataBound: Int) {
def unapply(arg: Option[Int]): Boolean = arg match {
case None => true
case Some(data) if data > dataBound => true
case _ => false
}
}
val GreaterThan50OrEmpty = new GreaterThanOrEmpty(50)
data match {
case GreaterThan50OrEmpty() => println("matches pattern")
case _ => println("default")
}
您甚至可以自动生成这样的unapply(尽管我想这不值得)
import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.language.experimental.macros
import scala.reflect.macros.blackbox
@compileTimeOnly("enable macro paradise")
class extractor[A] extends StaticAnnotation {
def macroTransform(annottees: Any*): Any = macro ExtractorMacro.impl
}
object ExtractorMacro {
def impl(c: blackbox.Context)(annottees: c.Tree*): c.Tree = {
import c.universe._
val typA = c.prefix.tree match {
case q"new extractor[$a]" => a
}
annottees match {
case q"$mods object $tname extends { ..$earlydefns } with ..$parents { $self => ..$body }" :: Nil =>
val cases = tname.decoded.split('|').map(s => s"case $s => true").mkString("\n")
val casesTree = c.parse(
s"""arg match {
| $cases
| case _ => false
|}""".stripMargin)
q"""$mods object $tname extends { ..$earlydefns } with ..$parents { $self =>
..$body
def unapply(arg: $typA): Boolean = $casesTree
}"""
case _ => c.abort(c.enclosingPosition, "not object")
}
}
}
用途:
@extractor[Option[Int]]
object `Some(x) if x < 25 | None | Some(data) if data > 50`
//Warning:scalac: object ... extends scala.AnyRef {
// ...
// def unapply(arg: Option[Int]): Boolean = arg match {
// case Some((x @ _)) if x.$less(25) => true
// case None => true
// case Some((data @ _)) if data.$greater(50) => true
// case _ => false
// }
//}
def test(arg: Any) = arg match {
case `Some(x) if x < 25 | None | Some(data) if data > 50`() =>
println("matches pattern")
case _ => println("default")
}
test(None) // matches pattern
test(Some(51)) // matches pattern
test(Some(24)) // matches pattern
test(Some(30)) // default
2条答案
按热度按时间jxct1oxe1#
您可以使用
Option.forall
作为条件。f4t66c6m2#
通常,这样的模式匹配可以写成如下
如果这种组合(
None || Some(data) && data > 50
)经常发生,您可以引入定制的提取程序你甚至可以随意叫它
稍微笼统一点的方法
您甚至可以自动生成这样的
unapply
(尽管我想这不值得)用途: