July 14, 2008

using call-by-name parameters

At David's suggestion, I stole a logging idea from lift for configgy: using call-by-name parameters to avoid evaluating a log expression until we decide that some handler is actually going to log it (in other words, the formatter is called). Under the hood, scala is turning this:

log.ifDebug("got " + getCount + " of them")


into something like this:

log.ifDebug(new Function0[String] { def apply = { "got " + getCount + " of them" } })


I was worried for a few minutes that this might be a lot of overhead for a logging method, but convinced myself that the compiler is doing most of the work, and all that's happening at runtime is a "new", which would happen for almost any logging.

What I wanted, and eventually worked around, was a way to turn the call-by-name parameter "message" from the method name:

def ifDebug(message: => AnyRef)


into the function object that I knew scala was passing around. I tried casting, but the compiler was way too smart for me. Eventually I just wrote a method that would return the contents of message, and therefore evaluate the function. But I still think it would be nice if I could somehow sweet-talk the compiler into giving me the function object. Call-by-name is mostly for the syntactical-sugar convenience of the caller.

1 comment:

Anonymous said...

You can convert a by-name argument to a function by following the name with an underscore. Like this:

def tofunction[A](f: => A) = f _