Как написать предельную функцию в Scala? - PullRequest
4 голосов
/ 01 июня 2011

Задумавшись об определенных ошибках в моем первом приложении Scala, я обнаружил, что моя функция предела не совсем работает ... вообще!

Итак, вот моя первая попытка :

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

Всегда возвращается x!

Моя вторая попытка выглядела так:

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

и это сработало.

Итак, мой вопрос: почему min; и max; из первого примера в основном не активны, а x; нет? И моя вторая попытка - хорошая Скала?

Ответы [ 4 ]

14 голосов
/ 01 июня 2011

Или даже:

val limited = lower max x min upper

max и min имеют одинаковые приоритеты и ассоциированные слева, поэтому паренсы не нужны

8 голосов
/ 01 июня 2011

Я написал обобщенную версию этого (которую я назвал clamp), которая выглядит следующим образом:

// 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
}

В Scala результатом выражения является последнее значение, упомянутое вэто выражение.Результат выражений if в вашей первой попытке отбрасывается, потому что за каждым выражением if следует другое выражение.Ваша вторая попытка в порядке, но вы можете сделать это с if ... else, как в моем примере.Вы можете написать свое так:

def limit(x: Double, min: Double, max: Double): Double =
  if (x < min) min else if (x > max) max else x
7 голосов
/ 01 июня 2011

Если вы не укажете return явно, тогда возвращаемое значение будет результатом последнего выражения.В вашем первом примере ваше последнее выражение - x;, поэтому оно будет возвращено в любом случае.Если вы хотите вернуть другое значение, вы можете использовать if/else if/else:

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

В этом случае if/else if/else обрабатывается как одно выражение, которое возвращает одно значение.

Вы также можетеиспользуйте сопоставление с шаблоном следующим образом (это также одиночное выражение):

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

Я не думаю, что ваш второй пример можно охарактеризовать как «хороший scala».В таком простом случае все усложняется и имеет 3 точки возврата (вместо одной точки возврата).Это также добавляет больше ненужных шаблонов.

3 голосов
/ 01 июня 2011

Почему бы просто:

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

или

val limited = (lower max x) min upper
...