Type-dependent Closures touches on this (and, in fact, this page used to be TypeDependentClosures ), but it is a bit unclear as to what it’s communicating. Certainly it describes closures, but mostly talks about how the syntax shown results in evaluation at a time different than what you might think.
Suppose you wish to create a logging framework that encourages detailed and dynamic log messages (e.g.
"You tried to access port " + port + " of url " + url + "and got the error " + error). In Java, you would wrap messages like this in an
if statement that checks to see if the runtime logging level is sufficient to generate the message before you actually construct it.
In Scala, we can use closures to achieve this without any complicated conditionals around our logging statements.
Note that the log level is not sufficient to generate debug messages. When this program runs, we see, via our
breadcrumb method that the “RED ALERT” message was created (and printed), but also that the message passed to the
javaDebug method was created (and not printed), but not the messages in the other two
This is because the log message’s parameters are ‘’pass by name’’. This means that the parameters aren’t evaluated until they are need (and not evaulated if they aren’t). For the debug messages, these blocks don’t get called. (and thus, our complicated string concatenations don’t execute).
=> String is different than
() => String; the first form indicates that a
String is expected, but will be passed by name, not value; the second indicates a function taking no arguments and returning a
String is expected. This is somewhat subtle, as you could certainly think of the first case as a no-arg function that returns a
Also note that the parameters have access to the scope in which they were created, since they are technically closures. If we were to set the log level to 10, the output would be:
BREADCRUMB This is a simple debug message... BREADCRUMB This is a complicated debug test debug message... BREADCRUMB This is a mucho complicated debug test debug message... BREADCRUMB RED ALERT...
Notice how the value of “complex” changes between the calls, and the closures use the correct value. In Java, this would not be possible; the variables would have to be declared
We can take this to the next level by applying FunctionCurrying . Suppose we wanted to bring back the ternary operator that Scala doesn’t seem to include.
So, we define a method named
? that takes three expressions. The first must evaluate to a boolean, and the second two must evaluate to the same type (that we don’t know). When the method is called, we evaluate the first expression. If it returns true, we evaluate the second expression, otherwise we evaluate the third.
Note that since these are closures, only one of the second two expressions will get evaluated.
My Thoughts on this Feature
This is a great feature and one of my top reasons to use Scala. While the second example of adding in generics and currying certainly stretches some bounds, it demonstrates how Scala’s (often weird) syntax can be used to extend the language and make it appear to have new control structures and keywords.