2011-09-27 12 views
11

以下のScalaコードを考慮してください。複数の一致でのパターンマッチング

val a = "both" 

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

a == "both"場合、Scalaは両方のケースを実行するように、私は仕事にmatchをしたいと思います。これが可能か、私が望むものを達成するための選択肢がありますか?

+0

可能重複[マッチ「フォールスルー」:?複数のケースのためのコードの同じ部分を実行します](http://stackoverflow.com/questions/2325863/match-フォールスルー - 同じコードを複数の場合に実行する) – nawfal

答えて

25

標準的なパターンマッチングは、ちょうど1つの場合に常に一致します。

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' 
:あなたはパターンが部分関数として扱うことができるという事実を利用して近くにあなたが欲しいものを得ることができるといえ、独自のマッチング演算子を定義することによって( Language Specification、セクション8.5、 無名関数パターンマッチングを参照してください)

シンタックスは通常通りですが、私にとっては、このような構造はScalaの威力を証明しています。

あなたの例は、現在のように書かれ

:(編集huynhjlは、彼がthis questionに驚くほど似た答えを与えたことを指摘した。)

+1

これは驚くほどクリーンなソリューションです。よくやった! –

+1

+1 "scrutinee" –

+1

これは私にhttp://stackoverflow.com/questions/6720205/idiomatic-way-to-convert-a-seqb/6720659#6720659を思い出させます。 '=> S'という名前のメリットは何ですか? – huynhjl

0

1つの可能な方法は次のようになります。

val a = "both" 

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

matchは1を実行し、一つだけ、例、あなたが試合で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") 
}) 

そして、あなたは重要なコード(この場合はprintln秒)のいずれかを複製していません。

6

を明白なキャプテンであることのリスクでは、場合に

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

このように、パターンマッチングを忘れてifを使うのが最も簡単です。

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

a ==心配を繰り返します場合は、代わりにSetapply方法はcontainsと同じこと、と少し短いことを利用して

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

を書くことができます。

1

2回だけ一致:

val a = "both" 

a match { 
    case "both" | "foo" => println ("foo") // Case 1 
} 
a match { 
    case "both" | "bar" => println ("bar") // Case 2 
} 
関連する問題