2009-02-11

Scala custom syntax: "after"

I've run into this pattern a few times where I want to return the value of some expression, but I also need to do some side-effect between evaluating the expression and returning its value. For example, putting the result into a cache. Or, setting some additional state in a constructed object. The normal way of doing this involves putting the value of the expression into a temporary variable, performing whatever other operations are needed and then returning the value of the temporary. That is fine but it turns into at least three lines of code and some cases are so simple you might wish you could do it all on one line and not bother naming a temporary.

I recently gave a presentation on "Sampling Scala" and ended up developing a Scala custom syntax addition to handle it. At the Scala BASE meeting at Googleplex last night, Jorge Ortiz was showing a Lift Chat server example and it had this piece of code:

  private val server = {
    val ret = ChatServer.server
    ret ! ChatServerAdd(this)
    ret
  }

Which demonstrates the situation. I'd much rather write that:

  private val server = ChatServer.server after { _ ! ChatServerAdd(this) }

Here's the way to implement after:

object After {
  implicit def any2After[A](value: A) = new After(value)

  class After[A](val value: A) {
    def after[B](f: A => B) : A = { f(value); value }
  }
}

And, here is another example of using it:

import collection.mutable.Map
import After._

val cache = Map[Int, Int]()
  
def foo(x : Int) : Int = {
  val y = // ...

  return y after { cache(x) = _ } // like finally, with an arg
} 

No comments: