0
votes

While playing around in Scala, I came up against something that I think should be possible, but I don't know how to do.

I'm returning a value that's bounded by a given min/max. With an if-else statement, the function would look like this:

def set(n: Int, min: Int, max: Int): Int = 
{
  if (n < min) return min
  if (n > max) return max
  return n
}

I was wondering if it was possible to do this (elegantly) with pattern matching. I tried the following, but it was syntactically incorrect:

def set(n: Int, min: Int, max: Int): Int = n match 
{
  case (n < min) => min
  case (n > max) => max
  case _ => n
}

I think there's a way to do it by mixing case and if statements, but by the time I've done that I might as well just be using a standard if/else chain. Is there a correct syntax to do what I'm attempting?

2
def set(...) is declared type Unit, but returns a value. I guess you want it to be set(...):Int ? - maasg
@maasg Oops, wasn't thinking there. Fixed. Question still stands, though. - KChaloux

2 Answers

10
votes

Pattern matching works but is less elegant:

def set(n: Int, min: Int, max: Int) = n match {
  case _ if n < min => min
  case _ if n > max => max
  case _ => n
}

because:

def set(n: Int, min: Int, max: Int) = if (n < min) min else if (n > max) max else n

(or if you like line breaks:

def set(n: Int, min: Int, max: Int) = {
  if (n < min) min
  else if (n > max) max
  else n
}

)

Return not needed.

(Don't forget math.min(max,math.max(min,n)), either.)

1
votes

Using the return expression you are thinking/programming in imperative terms. if this happens, then return that. In Scala, if is a typed expression:

val x = if (cond) v1 else v2

where x will be of the most specific type that is a supertype of v1 and v2.

So, you can write your expressions as:

def bound(n:Int, max:Int, min:Int) = if (n < min) min else if (n>max) max else n

Even when it can be done with guards, I don't see value in using a match statement in this case.