web-dev-qa-db-ja.com

Scalaのパターンマッチングシステムで比較演算子を使用する

Scalaのパターンマッチングシステムを使用して比較で一致させることは可能ですか?例えば:

a match {
    case 10 => println("ten")
    case _ > 10 => println("greater than ten")
    case _ => println("less than ten")
}

2番目のcaseステートメントは違法ですが、「aがより大きい場合」を指定できるようにしたいと思います。

145

ガード、つまりパターンの後にifとブール式を追加できます:

a match {
    case 10 => println("ten")
    case x if x > 10 => println("greater than ten")
    case _ => println("less than ten")
}

編集:これはifafter=>。これは、ガードが真でない場合にパターンwo n'tと一致するためです。

277
Ben James

述語を一致句に組み込む方法を尋ねた質問の精神に対する非回答として、この場合、述語はmatchの前に因数分解できます。

_def assess(n: Int) {
  println(
    n compare 10 match {
      case 0 => "ten"
      case 1 => "greater than ten"
      case -1 => "less than ten"
    })
}
_

現在、 scala.math.Ordering.compare(T, T)のドキュメント は、等しくない結果がgreater thanまたはゼロ未満。 Javaの Comparable#compareTo(T) は、Scalaの場合と同様に指定されます。 Scalaの 現在の実装 のように、それぞれ正の値と負の値にそれぞれ1と-1を使用するのが慣習的ですが、実装が変更されるリスクがなければ、そのような仮定を立てることはできません下から。

31
seh

私の意見では、ガードを追加するよりもはるかに読みやすいソリューション:

(n compare 10).signum match {
    case -1 => "less than ten"
    case  0 => "ten"
    case  1 => "greater than ten"
}

ノート:

  • Ordered.compare は、これより小さい場合は負の整数を返し、大きい場合は正の整数を返し、等しい場合は0を返します。
  • Int.signum 負の数(10未満)の場合はcompareから-1に出力を圧縮し、正の場合(10を超える場合)1 、または0がゼロ(10に等しい)の場合。
17
vergenzt

上記および以下のすべての回答は元の質問に完全に答えていますが、追加の情報がドキュメントに記載されています https://docs.scala-lang.org/tour/pattern-matching.html 私の場合は当てはまりませんでしたが、このstackoverflowの回答はGoogleの最初の提案であるため、上記の質問のコーナーケースである回答を投稿したいと思います。
私の質問は:

  • 関数の引数を持つ一致式でガードを使用する方法は?

言い換えることができます:

  • 関数の引数と一致式でif文を使用する方法は?

答えは以下のコード例です:

    def drop[A](l: List[A], n: Int): List[A] = l match {
      case Nil => sys.error("drop on empty list")
      case xs if n <= 0 => xs
      case _ :: xs => drop(xs, n-1)
    }

scala fiddle: https://scalafiddle.io/sf/G37THif/2 へのリンクは、case xs if n <= 0 => xsステートメントは、guard(if)ステートメントでn(関数の引数)を使用できます。

これが私のような人に役立つことを願っています。

1