Условный вызов метода в Scala - PullRequest
       3

Условный вызов метода в Scala

12 голосов
/ 06 сентября 2011

Я нашел этот шаблон довольно много раз в своем коде:

  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)

У кого-нибудь есть идея получше? Я скучаю по магии Скалаза?

Ответы [ 3 ]

18 голосов
/ 06 сентября 2011
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
3 голосов
/ 03 марта 2016

Я не могу прокомментировать ваш ответ @Rex Kerr, но более краткий способ сделать это будет:

implicit class When[A](a: A) {
  def when(f: A => Boolean)(g: A => A) = if (f(a)) g(a) else a
}

Просто поставив implicit перед классом, вы можете опустить неявную функциюполностью.

0 голосов
/ 03 марта 2016

Если вы представляете свой callAMethod как эндоморфизм, тогда вы можете использовать моноидную функциональность.Что-то вроде:

object |> valueOrZero(doIt, Endo(_.callAMethod))

(может потребоваться параметр типа на Endo)

...