Почему реализация Monaz for Option в Скалазе дважды оценивает функцию f2?
Определение опции моноида скаляза следующее:
implicit def optionMonoid[A: Semigroup]: Monoid[Option[A]] = new Monoid[Option[A]] {
def append(f1: Option[A], f2: => Option[A]) = (f1, f2) match {
case (Some(a1), Some(a2)) => Some(Semigroup[A].append(a1, a2))
case (Some(a1), None) => f1
case (None, Some(a2)) => f2
case (None, None) => None
}
def zero: Option[A] = None
}
f2
является параметром передачи по имени, что означает, что каждый вызов оценивает выражение. Зачем его нужно оценивать снова, когда оно только что оценивалось в сопоставлении с образцом? возврате Some(a2)
должен быть такой же результат и выражение f2
может быть очень дорогим.
Я что-то пропустил?
1 ответ
Мне кажется, что это было написано, чтобы подчеркнуть симметрию проблемы и для ясности, а не для скорости. Вы не можете просто отбросить лень второго аргумента, так как Semigroup
определяет это таким образом, и в других случаях лень второго аргумента может быть существенной. Чтобы сохранить визуальное представление симметрии задачи, вы, вероятно, хотите просто добавить
val g2 = f2 // Force evaluation
(f1, g2) match { ...
или что-то подобное.
(Было бы хорошо, если бы аргументы по имени назывались ленивыми, чтобы автоматически их запоминать.)