使用连词进行模式匹配(PatternA AND PatternB)

发布于 2024-08-22 01:26:58 字数 1379 浏览 10 评论 0原文

Scala 有一个语言功能来支持模式匹配中的析取(“模式替代”):

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

但是,如果审查满足 PatternA PatternB (合取),我经常需要触发一个操作。

我创建了一个模式组合器'&&'这增加了这种能力。三句小诗让我想起了为什么我喜欢 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 _ => "_"
}

讨论要点

  1. 是否有现有的方法可以做到这一点?
  2. 这种方法有问题吗?
  3. 这种方法可以创建任何其他有用的组合器吗? (例如,Not
  4. 这样的组合器是否应该添加到标准库中?

更新 我刚刚被问到编译器如何解释 case A &&住宿加早餐旅馆C。这些是中缀运算符模式(Scala 参考的第 8.1.9 节)。您还可以使用标准提取模式 (8.1.7) 将其表示为 &&(&&(A, B), C)。请注意表达式如何从左到右关联,就像普通的中缀运算符方法调用一样,例如Boolean#&inval b = true &&假&&是的`。

Scala has a language feature to support disjunctions in pattern matching ('Pattern Alternatives'):

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

However, I often need to trigger an action if the scrutiny satisfies PatternA and PatternB (conjunction.)

I created a pattern combinator '&&' that adds this capability. Three little lines that remind me why I love 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 _ => "_"
}

Points for discussion

  1. Is there an existing way to do this?
  2. Are there problems with this approach?
  3. Can this approach create any other useful combinators? (for example, Not)
  4. Should such a combinator be added to the standard library?

UPDATE
I've just been asked how the compiler interprets case A && B && C. These are infix operator patterns (Section 8.1.9 of the Scala Reference). You could also express this with standard extract patterns (8.1.7) as &&(&&(A, B), C).' Notice how the expressions are associated left to right, as per normal infix operator method calls likeBoolean#&&inval b = true && false && true`.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

路还长,别太狂 2024-08-29 01:26:58

我真的很喜欢这个技巧。我不知道有任何现有的方法可以做到这一点,而且我预计它不会出现任何问题——但这并没有多大意义。我想不出任何方法来创建 Not

至于将其添加到标准库中......也许吧。但我觉得有点难。另一方面,如何说服 Scalaz 人员将其纳入其中?它看起来更像是他们自己的辖区。

I really like this trick. I do not know of any existing way to do this, and I don't foresee any problem with it -- which doesn't mean much, though. I can't think of any way to create a Not.

As for adding it to the standard library... perhaps. But I think it's a bit hard. On the other hand, how about talking Scalaz people into including it? It looks much more like their own bailiwick.

德意的啸 2024-08-29 01:26:58

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

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

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

A possible problem with this is the bloated translation that the pattern matcher generates.
Here is the translation of the sample program, generated with scalac -print. Even -optimise fails to simplify the if (true) "_" else throw new MatchError() expressions.

Large pattern matches already generate more bytecode than is legal for a single method, and use of this combinator may amplify that problem.

If && was built into the language, perhaps the translation could be smarter. Alternatively, small improvements to -optimise could help.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文