开发者

How to write a limit function in Scala?

After wondering about certain bugs in my first Scala application, I discovered that my limit function was not quite working ... at all!

So here was my first attempt:

  def limit(x : Double, min: Double, max : Double) = {
    if (x < min) min;
    if (x > max) max;
    x;
  }

It always returned x!

My second attempt looked like this:

  def limit(x : Double, min: Double, max : Double) : Double = {
    if (x < min) 开发者_Python百科return min;
    if (x > max) return max;
    x;
  }

and it worked.

So my question: why are min; and max; from the first example basically no-ops, and x; is not? And is my second attempt good Scala?


Or even:

val limited = lower max x min upper

max and min have the same precedence and associate left, so no parens are needed


I've written a generic version of this (which I had called clamp), which looks like this:

// NOTE: This will still do some boxing and unboxing because Ordering / Ordered is not @specialized.
@inline def clamp[@specialized(Int, Double) T : Ordering](value: T, low: T, high: T): T = {
  import Ordered._
  if (value < low) low else if (value > high) high else value
}

In Scala, the result of an expression is the last value mentioned in that expression. The result of the if-expressions in your first attempt is thrown away, because each if-expression is followed by another expression. Your second attempt is ok but you could do it with if ... else like in my example. You could write yours like this:

def limit(x: Double, min: Double, max: Double): Double =
  if (x < min) min else if (x > max) max else x


If you don't specify return explicitly, then return value is the result of the last expression. In your first example your last expression is x;, so it would be returned in any case. If you want to return different value, then you can use if/else if/else:

def limit(x : Double, min: Double, max : Double) = 
    if (x < min) min
    else if (x > max) max
    else x

In this case if/else if/else is treated as single expression that returns single value.

You can also use pattern matching like this (it's also single expression):

def limit(x : Double, min: Double, max : Double) = x match {
    case x if x < min => min
    case x if x > max => max
    case _ => x
}

I don't think that your second example can be described as "good scala". In such simple case it just complicates the whole thing and has 3 points of return (instead of single point of return). It also adds more unnecessary boilerplate.


Why not just:

import math.{min, max}
val limited = min(max(lower, x), upper)

or

val limited = (lower max x) min upper
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜