Mon 28 Nov 2011
By-name parameters (Lazy parameters)
Scala has an interesting feature, by-name parameters, that can take a little time to get your head around. Take the following code:
def foo() = {
println("in foo")
"FOO"
}
def bar(baz: => String) = {
println("in baz")
println(baz)
baz
}
bar(foo())
What do you think is the output of this scala snippet? Coming from Java, I would expect the following:
in foo
in baz
FOO
Much to my surprise, the code actually outputs the following:
in baz
in foo
FOO
in foo
In scala, when you declare a method parameter like baz: => String the parameter is not evaluated until it is used in the method body. But… be careful, because it will get evaluated each time the parameter is used within the method body.
Where would this behavior be valuable? Anywhere you can have an expensive computation that might not be needed in the method body. One common place might be a logging method.
def log(message: => String) {
if(notLogging) return
writeToLogFile(message)
}
log("hello there " + calculateExpensiveLogStatement())
In the above log statement, "hello there" + calculateExpensiveLogStatement() will not be evaluated until the message parameter is used in the log method. How does this work? I am not really sure
, but I think of it as scala generating an anonymous function for each invocation of the log method. This allows message to not be evaluated until it is used, just as if we had passed in a function pointer.
Thoughts?

This, in combination with Scala’s flexibility in parens vs block usage for parameters, is also how scala achieves the ability to support library features as though they were language features. From an example I recently implemented…
def requiresRole(role: string)(action: => Unit) {
if(roles.contains(role) {
action;
}
}
This can be invoked in consuming code as:
requiresRole(”admin”) {
println(”I am an admin”);
}
Which looks and feels like its a supported language keyword, instead of having to define and pass () => T blocks everywhere.
@Justin – Good point. I missed that use case. Thanks for reading.