Расчет базовой цены за дополнительную плату условия


Следующий код имеет много условных операторов. Я пытаюсь написать это в функциональном стиле программирования.

val basePrice = {
  var b = 0.0

  if (runtime > 120)
    b += 1.5
  if ((day == Sat) || (day == Sun))
    b += 1.5
  if (!isParquet)
    b += 2
  if (is3D)
    b += 3
  b
}

Я думаю, что следующий код будет хороший подход, но, возможно, я осложняет это слишком много.

val basePrice = {
  List((runtime > 120, 1.5), 
       (day == Sat || day == Sun, 1.5),
       (!isParquet, 2.0),
       (is3D, 3.0)).foldLeft(0.0)((acum, cond) =>
     if (cond._1) acum + cond._2 else acum)
}

Как бы вы написать первый фрагмент кода с использованием функциональных Программирование?



Комментарии
4 ответа

Каждое условие является функцией. Возможно, вы могли бы написать более сжато, но я думаю, что код будет понятнее, если вы сделаете это:

def priceFunction(cond: => Boolean)(mod: Double => Double) = (_: Double) match {
case x if cond => mod(x)
case y => y
}

val modRuntime = priceFunction(runtime > 120)(_ + 1.5)
val modWeekend = priceFunction(day == Sat || day == Sun)(_ + 1.5)
val modParquet = priceFunction(!isParquet)(_ + 2.0)
val mod3d = priceFunction(is3D)(_ + 3.0)
val modifiers = List(
modRuntime,
modWeekend,
modParquet,
mod3d
)
val modifierFunction = modifiers reduceLeft (_ andThen _)

val basePrice = modifierFunction(0.0)

Название идентификаторов тут обсасывать, и я мог бы написать Валь модификаторы = modRuntime и modWeekend и modParquet и mod3d без проблем. Я выбираю помещая их в список , потому что это показывает, насколько хорошо он может масштабироваться.

Можно также сделать частичных функций и цепь их иначе, в тех случаях, когда вы хотите только первое условие.

Вы видите такие вещи, используемые в веб-платформ, таких как радостными голубыми глазами, лифт или нефильтрованное, например.

9
ответ дан 18 августа 2011 в 02:08 Источник Поделиться

Может быть, немного более читаемым:

val basePrice = List((runtime > 120, 1.5), 
(day == Sat || day == Sun, 1.5),
(!isParquet, 2.0),
(is3D, 3.0)).collect{case (true, b) => b}.sum

2
ответ дан 17 августа 2011 в 09:08 Источник Поделиться

Мне нравится ответ Дэниел С. собрал все. В любом случае, в дополнение к списку(...).сумму альтернатив нет:

val basePrice = {
0.0 +
(runtime > 120 ? 1.5 | 0) +
((day == Sat) || (day == Sun) ? 1.5 | 0) +
(!isParquet ? 2 | 0) +
(is3D ? 3 | 0)
}

Где ?| это тернарный оператор.

0
ответ дан 30 июня 2013 в 05:06 Источник Поделиться

Вы можете просто написать ее такой:

val basePrice = 0.0 +
(if (runtime > 120) 1.5 else 0) +
(if (day == Sat || day == Sun) 1.5 else 0) +
(if (!isParquet) 2 else 0) +
(if (is3D) 3 else 0)

0
ответ дан 21 июля 2013 в 01:07 Источник Поделиться