与连词模式匹配(PatternA AND PatternB)
Scala有一种语言function来支持模式匹配中的不连续(“模式select”):
x match { case _: String | _: Int => case _ => }
但是,如果审查满足PatternA 和 PatternB(连词),我经常需要触发一个动作。
我创build了一个模式组合器“&&”,增加了这个function。 三条小提醒我为什么爱Scala!
// 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 _ => "_" }
讨论要点
- 有没有现有的方法来做到这一点?
- 这种方法有问题吗?
- 这种方法可以创build任何其他有用的组合器? (例如,
Not
) - 如果这样的组合器被添加到标准库?
更新我刚刚被问及编译器如何解释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
&&(&&(A, B), C).' Notice how the expressions are associated left to right, as per normal infix operator method calls like
in
val b = true && false && true`中的&&(&&(A, B), C).' Notice how the expressions are associated left to right, as per normal infix operator method calls like
布尔值&&。
我真的很喜欢这个把戏。 我不知道现在有什么办法可以做到这一点,但是我也没有预料到会有什么问题 – 尽pipe这并不意味着太多。 我想不出有什么办法可以创build一个Not
。
至于将其添加到标准库…也许。 但是我认为这有点难。 另一方面,谈斯卡拉兹人怎么把它包括进来呢? 它看起来更像是他们自己的住所。
一个可能的问题是模式匹配器产生的膨胀的翻译。 这是用scalac -print
生成的示例程序的翻译 。 即使-optimise
不能简化if (true) "_" else throw new MatchError()
expression式。
大型模式匹配已经产生了比单一方法合法的更多的字节码,使用这种组合器可能会放大这个问题。
如果&&
是build立在语言的基础上的话,翻译可能会更聪明。 或者,对“ -optimise
小改进可能有所帮助。