Another tour of Scala

 
 
 
 

Type Dependent Closures

The Gist

Type-dependent Closures 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.

My Interpretation

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 debug methods.

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).

The syntax => String is different than () => String; the first form indicates a pass-by-name parameter that evaluates to a String is expected, while the second indicates a function taking no arguments and returning a String is expected. This is subtle on two levels. First, we can pass in a closure (a block of code) and it won’t be evaluated until it’s called. Secondly, a block code taking no parameters seems very similar to a function taking no parameters.

Note that the closures have access to the scope in which they were created. 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 final.

Another Level

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 pass-by-name closures, only one of the second two expressions will get evaluated.

My Thoughts on this Feature

Closures are solid gold. Money. I love them and all they do, and this is one of the 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.


Last Updated 09/21/2009 at 03:21:09 PM by davec

blog comments powered by Disqus