Ответ 1
class When[A](a: A) {
def when(f: A => Boolean)(g: A => A) = if (f(a)) g(a) else a
}
implicit def whenever[A](a: A) = new When(a)
Пример:
scala> "fish".when(_.length<5)(_.toUpperCase)
res2: java.lang.String = FISH
Я нашел этот шаблон несколько раз в моем коде:
if (doIt)
object.callAMethod
else
object
Мне интересно, может ли синтаксически более приятный способ написать вышеприведенный код, особенно, чтобы избежать повторения переменной object
. Что-то вроде:
// using the Scalaz "pipe" operator
// and "pimping" f: T => T with a `when` method
object |> (_.callAMethod).when(doIt)
К сожалению, строка выше не выполняется, потому что для вывода типа требуется тип параметра для (_.callAMethod)
.
Теперь мой лучший подход:
implicit def doItOptionally[T](t: =>T) = new DoItOptionally(t)
class DoItOptionally[T](t: =>T) {
def ?>(f: T => T)(implicit doIt: Boolean = true) =
if (doIt) f(t) else t
}
implicit val doIt = true
object ?> (_.callAMethod)
Неплохо, потому что я должен объявить implicit val
, но это окупается, если есть несколько цепочечных вызовов:
object ?> (_.callAMethod) ?> (_.callAnotherMethod)
У кого-то есть лучшая идея? Я пропустил здесь волшебство Scalaса?
class When[A](a: A) {
def when(f: A => Boolean)(g: A => A) = if (f(a)) g(a) else a
}
implicit def whenever[A](a: A) = new When(a)
Пример:
scala> "fish".when(_.length<5)(_.toUpperCase)
res2: java.lang.String = FISH
Я не могу прокомментировать ваш ответ @Rex Kerr, но более краткий способ сделать это:
implicit class When[A](a: A) {
def when(f: A => Boolean)(g: A => A) = if (f(a)) g(a) else a
}
Просто поместите implicit
до того, как класс позволит полностью опустить неявную функцию.
Если вы представляете свой callAMethod
как эндоморфизм, вы можете использовать моноидную функциональность. Что-то вроде:
object |> valueOrZero(doIt, Endo(_.callAMethod))
(может потребоваться параметр типа на Endo
)