Question

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 DoItOptionally[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?

Was it helpful?

Solution

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

OTHER TIPS

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)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top