簡體   English   中英

Scala模式匹配:參數化的提取器對象是否可能?

[英]Scala Pattern matching: Are parametrized extractor objects possible?

是否可以創建可以使用的Extractor對象,例如:

val x = 42

x match {
  case GreaterThan(80) => println("5")
  case GreaterThan(70) => println("4")
  case GreaterThan(60) => println("3")
  case GreaterThan(40) => println("2")
  case _ => println("1")
}

現在我知道if if構造是可能的,但我覺得它使我的代碼case MyMatcher(x) if MyCreteria(x) => _並且看起來多余: case MyMatcher(x) if MyCreteria(x) => _case MyMatcher(x) if MyCreteria(x) => _ ),我想避免這種情況。

似乎以你想要的方式濫用unapply將是非常棘手的(如果可能的話)。 為什么你不想使用match if子句?

object GreaterThan {
  def apply(x:Int, boundary:Int) = x > boundary
}

x match {
  case x if GreaterThan(x, 80) => println("5")
  case x if GreaterThan(x, 70) => println("4")
  case _ => println("1")
}

它比原始代碼更冗長。

或者,您可以發明一些匹配的自定義模擬:

class Matcher(val cond: Int => Boolean, command: => Unit) {
  def evaluate() = command
}

val matchers = Seq(
  new Matcher(_ > 80, {println("5")}),
  new Matcher(_ > 70, {println("4")}),
  new Matcher(_ > 60, {println("3")}),
  new Matcher(_ > 40, {println("2")}),
  new Matcher(_ => true, {println("2")})
)

val x = 42
matchers.find(_.cond(x)).foreach(_.evaluate())

但它更加冗長。

case語句中使用的Extractor對象需要具有unapply方法。 不幸的是,由於對象本身就是單例,因此無法創建這樣的參數化對象(afaik)。

在下面的代碼中,我規避了為每個限制創建特定的單例object

@ÁkosVandra:也許以下代碼是有用的(因為它最接近您的要求):

def main(args: Array[String]) : Unit = {
  val n = 42

  n match {
    case GreaterThan50(x) => println("5")
    case GreaterThan40(x) => println("4")
    case GreaterThan30(x) => println("3")
    case GreaterThan20(x) => println("2")
    case _ => println("somewhat")
  }
}

class GreaterThanLimit(val limit: Int) {
  def unapply(x: Int): Option[Int] = if (x > limit) Some(x) else None
}

object GreaterThan10 extends GreaterThanLimit(10)
object GreaterThan20 extends GreaterThanLimit(20)
object GreaterThan30 extends GreaterThanLimit(30)
object GreaterThan40 extends GreaterThanLimit(40)
object GreaterThan50 extends GreaterThanLimit(50)

編輯2015-09-17

根據ÁkosVandra的評論,人們可以使用Boolean而不是Option[_]編寫

def main(args: Array[String]) : Unit = {
  val n = 42

  n match {
    case GreaterThan50() => println("5")
    case GreaterThan40() => println("4")
    case GreaterThan30() => println("3")
    case GreaterThan20() => println("2")
    case _ => println("somewhat")
  }
}

class GreaterThanLimit(val limit: Int) {
  def unapply(x: Int) : Boolean = x > limit
}

object GreaterThan10 extends GreaterThanLimit(10)
object GreaterThan20 extends GreaterThanLimit(20)
object GreaterThan30 extends GreaterThanLimit(30)
object GreaterThan40 extends GreaterThanLimit(40)
object GreaterThan50 extends GreaterThanLimit(50)

你有什么理由不這樣做嗎? 它並不特別冗長,為您省去了一些麻煩。

x match {
  case _ if x > 80 => println("5")
  case _ if x > 70 => println("4")
  case _ if x > 60 => println("3")
  case _ if x > 40 => println("2")
  case _ => println("1")
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM