与连词模式匹配(模式和模式)

时间:2010-02-14 14:18:06

标签: scala pattern-matching

Scala有一种语言功能来支持模式匹配中的分离('Pattern Alternatives'):

x match {
    case _: String | _: Int => 
    case _ =>
}

但是,如果审查满足PatternA PatternB(连接),我经常需要触发操作。

我创建了一个模式组合器'&&'这增加了这种能力。三条小线条让我想起为什么我喜欢斯卡拉!

// Splitter to apply two pattern matches on the same scrutiny.
object && {
  def unapply[A](a: A) = Some((a, a))
}

// Extractor object matching first character.
object StartsWith {
  def unapply(s: String) = s.headOption
}

// Extractor object matching last character.
object EndsWith {
  def unapply(s: String) = s.reverse.headOption
}

// Extractor object matching length.
object Length {
  def unapply(s: String) = Some(s.length)
}

"foo" match {
  case StartsWith('f') && EndsWith('f') => "f.*f"
  case StartsWith('f') && EndsWith(e) && Length(3) if "aeiou".contains(e) => "f..[aeiou]"
  case _ => "_"
}

讨论要点

  1. 有现成的方法吗?
  2. 这种方法有问题吗?
  3. 这种方法可以创建任何其他有用的组合器吗? (例如,Not
  4. 是否应将这样的组合子添加到标准库中?
  5. 更新 我刚刚被问到编译器如何解释case A && B && C。这些是中缀运算符模式(Scala参考的第8.1.9节)。您也可以使用标准提取模式(8.1.7)表示为&&(&&(A, B), C).' Notice how the expressions are associated left to right, as per normal infix operator method calls like布尔#&& in val b = true&&虚假&& TRUE`。

2 个答案:

答案 0 :(得分:13)

我真的很喜欢这个伎俩。我不知道有任何现有的方法可以做到这一点,我也没有预见到它的任何问题 - 但这并不意味着什么。我想不出有任何方法来创建Not

至于将它添加到标准库......也许吧。但我认为这有点难。另一方面,如何与Scalaz人交谈包括它?它看起来更像是他们自己的bailiwick。

答案 1 :(得分:11)

这可能是一个问题,即模式匹配器生成的膨胀转换。 以下是使用scalac -print生成的示例程序的translation。即使-optimise无法简化if (true) "_" else throw new MatchError()表达式。

大型模式匹配已经生成了比单个方法更合法的字节码,使用这个组合器可能会放大这个问题。

如果语言中内置&&,翻译可能会更智能。或者,-optimise的小改进可能有所帮助。