Using comparison operators in Scala's pattern matching system
Is it possible to match on a comparison using the pattern matching system in Scala? For example:
a match {
case 10 => println("ten")
case _ > 10 => println("greater than ten")
case _ => println("less than ten")
}
The second case statement is illegal, but I would like to be able to specify "when a is greater than".
You can add a guard, i.e. an if
and a boolean expression after the pattern:
a match {
case 10 => println("ten")
case x if x > 10 => println("greater than ten")
case _ => println("less than ten")
}
Edit: Note that this is more than superficially different to putting an if
after the =>
, because a pattern won't match if the guard is not true.
As a non-answer to the question's spirit, which asked how to incorporate predicates into a match clause, in this case the predicate can be factored out before the match
:
def assess(n: Int) {
println(
n compare 10 match {
case 0 => "ten"
case 1 => "greater than ten"
case -1 => "less than ten"
})
}
Now, the documentation for scala.math.Ordering.compare(T, T)
promises only that the non-equal outcomes will be greater than or less than zero. Java's Comparable#compareTo(T)
is specified similarly to Scala's. It happens to be conventional to use 1 and -1 for the positive and negative values, respectively, as Scala's current implementation does, but one can't make such an assumption without some risk of the implementation changing out from underneath.
A solution that in my opinion is much more readable than adding guards:
(n compare 10).signum match {
case -1 => "less than ten"
case 0 => "ten"
case 1 => "greater than ten"
}
Notes:
-
Ordered.compare
returns a negative integer if this is less than that, positive if greater, and0
if equal. -
Int.signum
compresses the output fromcompare
to-1
for a negative number (less than 10),1
for positive (greater than 10), or0
for zero (equal to 10).
While all the above and bellow answers perfectly answer the original question, some additional information can be found in the documentation https://docs.scala-lang.org/tour/pattern-matching.html , they didn't fit in my case but because this stackoverflow answer is the first suggestion in Google I would like to post my answer which is a corner case of the question above.
My question is:
- How to use a guard in match expression with an argument of a function?
Which can be paraphrased:
- How to use an if statement in match expression with an argument of a function?
The answer is the code example below:
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)
}
link to scala fiddle : https://scalafiddle.io/sf/G37THif/2
as you can see the case xs if n <= 0 => xs
statement is able to use n(argument of a function) with the guard(if) statement.
I hope this helps someone like me.