开发者

Conditional invocation of a method in Scala

I've found this pattern quite a few times in my code:

  if (doIt)
    object.callAMethod
  else
    object

I'm wondering if there could be a syntactically more pleasing way to write the code above, especially to avoid the repetition of the object variable. Something like:

   // using the Scalaz "pipe" operator
   // and "pimping" f: T => T with a `when` method
   object |> (_.callAMethod).when(doIt)

Unfortunately the line above fails because the type inference requires a parameter type for (_.callAMethod).

My best approach for now is this:

    implicit def doItOptionally[T](t: =>T) = new DoItOptionally(t)
    class DoItOp开发者_JAVA技巧tionally[T](t: =>T) {
      def ?>(f: T => T)(implicit doIt: Boolean = true) = 
        if (doIt) f(t) else t
    } 

    implicit val doIt = true
    object ?> (_.callAMethod)

Not great because I have to declare an implicit val but this pays off if there are several chained calls:

     object ?> (_.callAMethod) ?> (_.callAnotherMethod)

Does anyone have a better idea? Am I missing some Scalaz magic here?


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)

Example:

scala> "fish".when(_.length<5)(_.toUpperCase)
res2: java.lang.String = FISH


I can't comment on your answer @Rex Kerr but a more concise way to do that would be:

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

Just putting the implicit before the class allows you to omit the implicit function entirely.


If you represent your callAMethod as an endomorphism then you can use the monoid functionality. Something like:

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

(might need a type parameter on the Endo)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜