Другая возможность:
def avg(left: Option[Double], right: Option[Double])(default: => Double): Double =
left.flatMap(a => right.map(b => (a + b) / 2))
.orElse(left)
.orElse(right)
.getOrElse(default)
Вы flatMap
над левой опцией: если она не пустая, вы выбираете правильную опцию и map
ее содержимое и усредняете с содержанием левой опции. Если какой-либо из параметров пуст, результат будет None
, поэтому вы можете определить либо left
, либо right
как запасные значения с помощью orElse
. Наконец, результат извлекается с помощью getOrElse
, и, если оба входа пустые, возвращается default
.
Вы можете адаптировать его для принятия любого поведения. Чтобы создать функцию, которая выдает, если обе опции пусты, вы можете сделать следующее:
val assertAvg = avg(_ : Option[Double], _ : Option[Double])(sys.error("both operands are empty"))
Это работает, потому что типом throw
выражений является Nothing
, который является подтипом любого другого типа ( включая Double
), т.е. он может быть возвращен в результате любого выражения, независимо от ожидаемого типа.
Код (и некоторые тесты) доступны здесь, в Scast ie .