具有多个匹配项的模式匹配

发布于 2024-12-06 19:51:05 字数 293 浏览 4 评论 0 原文

考虑以下 Scala 代码。

val a = "both"

a match {
    case "both" | "foo" => println ("foo")   // case 1
    case "both" | "bar" => println ("bar")   // case 2
}

我希望 match 能够工作,以便如果 a == "both",Scala 将执行这两种情况。这是可能的还是有其他选择来实现我想要的?

Consider the following Scala code.

val a = "both"

a match {
    case "both" | "foo" => println ("foo")   // case 1
    case "both" | "bar" => println ("bar")   // case 2
}

I would like match to work so that if a == "both", Scala will execute both cases. Is this possible or are there any alternatives to achieve what I want?

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

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

发布评论

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

评论(5

差↓一点笑了 2024-12-13 19:51:05

标准模式匹配将始终只匹配一种情况。通过使用模式可以被视为部分函数这一事实,您可以接近您想要的内容(请参阅 语言规范,第 8.5 节,模式匹配匿名函数)并通过定义您自己的匹配运算符,虽然:

class MatchAll[S](scrutinee : =>S) {
  def matchAll[R](patterns : PartialFunction[S,R]*) : Seq[R] = {
    val evald : S = scrutinee
    patterns.flatMap(_.lift(evald))
  }
}

implicit def anyToMatchAll[S](scrut : =>S) : MatchAll[S] = new MatchAll[S](scrut)

def testAll(x : Int) : Seq[String] = x matchAll (
  { case 2 => "two" },
  { case x if x % 2 == 0 => "even" },
  { case x if x % 2 == 1 => "neither" }
)

println(testAll(42).mkString(",")) // prints 'even'
println(testAll(2).mkString(","))  // prints 'two,even'
println(testAll(1).mkString(","))  // prints 'neither'

语法稍微偏离通常,但对我来说这样一个构造仍然是Scala 力量的见证。

你的例子现在写成:(

// prints both 'foo' and 'bar'
"both" matchAll (
  { case "both" | "foo" => println("foo") },
  { case "both" | "bar" => println("bar") }
)

编辑huynhjl指出他给出了一个可怕的相似答案到这个问题。)

Standard pattern-matching will always match on only exactly one case. You can get close to what you want by using the fact that patterns can be treated as partial functions (see the Language Specification, Section 8.5, Pattern Matching Anonymous Functions) and by defining your own matching operator, though:

class MatchAll[S](scrutinee : =>S) {
  def matchAll[R](patterns : PartialFunction[S,R]*) : Seq[R] = {
    val evald : S = scrutinee
    patterns.flatMap(_.lift(evald))
  }
}

implicit def anyToMatchAll[S](scrut : =>S) : MatchAll[S] = new MatchAll[S](scrut)

def testAll(x : Int) : Seq[String] = x matchAll (
  { case 2 => "two" },
  { case x if x % 2 == 0 => "even" },
  { case x if x % 2 == 1 => "neither" }
)

println(testAll(42).mkString(",")) // prints 'even'
println(testAll(2).mkString(","))  // prints 'two,even'
println(testAll(1).mkString(","))  // prints 'neither'

The syntax is slightly off the usual, but to me such a construction is still a witness to the power of Scala.

Your example is now written as:

// prints both 'foo' and 'bar'
"both" matchAll (
  { case "both" | "foo" => println("foo") },
  { case "both" | "bar" => println("bar") }
)

(Edit huynhjl pointed out that he gave a frighteningly similar answer to this question.)

抚笙 2024-12-13 19:51:05

冒着成为明显队长的风险,在这种情况下,最简单的方法就是忘记模式匹配并使用 if

if (a == "both" || a == "foo") println("foo")
if (a == "both" || a == "bar") println("bar") 

如果 a == 的重复让您担心,您可以

if (Set("both", "foo")(a)) println("foo")
if (Set("both", "bar")(a)) println("bar")

使用 Set 上的 apply 方法与 相同的事实来 编写>包含,并且有点短。

At risk of being Captain Obvious, in a case like this it would be simplest just to forget pattern matching and use if.

if (a == "both" || a == "foo") println("foo")
if (a == "both" || a == "bar") println("bar") 

If the repetition of a == worries you, you could instead write

if (Set("both", "foo")(a)) println("foo")
if (Set("both", "bar")(a)) println("bar")

using the fact that the apply method on Set does the same as contains, and is a bit shorter.

雨的味道风的声音 2024-12-13 19:51:05

match 执行一种且仅一种情况,因此您不能在匹配中将其作为 or 执行。但是,您可以使用列表和 map/foreach

val a = "both"
(a match {
  case "both" => List("foo", "bar")
  case x => List(x)
}) foreach(_ match {
  case "foo" => println("foo")
  case "bar" => println("bar")
})

并且您不会重复任何重要代码(在本例中为 printlns)。

match executes one, and only one, of the cases, so you can't do this as an or in the match. You can, however, use a list and map/foreach:

val a = "both"
(a match {
  case "both" => List("foo", "bar")
  case x => List(x)
}) foreach(_ match {
  case "foo" => println("foo")
  case "bar" => println("bar")
})

And you're not duplicating any of the important code (in this case the printlns).

雨轻弹 2024-12-13 19:51:05

只需匹配两次:

val a = "both"

a match {
    case "both" | "foo" => println ("foo")   // Case 1
}
a match {
    case "both" | "bar" => println ("bar")   // Case 2
}

Just match twice:

val a = "both"

a match {
    case "both" | "foo" => println ("foo")   // Case 1
}
a match {
    case "both" | "bar" => println ("bar")   // Case 2
}
万水千山粽是情ミ 2024-12-13 19:51:05

一种可能的方法是:

val a = "both"

a match {
  case "foo" => println ("foo")   // Case 1
  case "bar" => println ("bar")   // Case 2
  case "both" => println ("foo"); println ("bar")
}

One possible way could be:

val a = "both"

a match {
  case "foo" => println ("foo")   // Case 1
  case "bar" => println ("bar")   // Case 2
  case "both" => println ("foo"); println ("bar")
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文