In this article, I’ll describe my exploration of closures: what they are, why programmers love them so darn much, and what your CFML code might look like if they were to be introduced into the language. A paragraph worth of disclaimers wherein I basically admit “I don’t know what I’m talking about” will follow. But I figured that was no way to pull you in, so… without further adieu, let’s start.
The Problem
I’m learning that most advances in one’s thinking start with a problem. This should be common-sense. It’s not like we sit in our chairs all day thinking “I wonder if I can come up with a nifty solution to something today.” Rather, we have problems to solve, we think about the existing solutions, and every once in a while, we realize that what we currently can do isn’t what we should do. Sometimes, the solution hasn’t been born yet. This originality is rare and I’ll leave it to really, really, really smart people. Often, the currently-unavailable solution has already been born, just in other contexts. In my case, the problem I was trying to solve would have been neatly handled if CFML had closures, which I knew about from various other languages. So let’s talk about the problem, and why closures are a nice way to approach it. I apologize in advance if this specific problem seems confusing. I thought about drumming up a fake problem for sake of clarity, but I decided against that. Real-world problems, though harder to initially grok, have always helped me more fully understand things, even if it takes two reads.
I have a “Formatter” component. It’s a utility component that does some all-purpose formatting of financial data. Dollars, percents, that sort of junk. This is CF, not Java, and as such we’re not in the business of passing around “Money” objects when a simple decimal value will do. Consequently, it’s useful to be able to pass these values through a Formatter object for display purposes (think: barcharts, tabular data, etc) while still retaining their raw value for use in calculations and whatnot.
I have a “TableBuilder” component. Its purpose is to take arrays of raw data in an “addTableRow” function and turn them into tables for display. This builder accepts various formatting options, the raw data (one row at a time), and can when requested add additional rows/columns based on the raw data (doing other calculations, etc) as a convenience. When it prints the raw data, it uses the Formatter
I have a “ThingThatUsesTableBuilder” component. This component’s job is to build a part of a PDF document. It does all manner of boring things – put some text here, put some text there, add some junk here, draw a box there – and also it needs to plop a table smack dab in the middle. It will use the TableBuilder for that purpose.
So: ThingThatUsesTableBuilder –>uses TableBuilder—>uses Formatter
When this TableBuilder was conceived, it was only ever meant to display integer values. As in, if it received decimal values, it rounded them. It was a “Very Bad Thing”(tm) if decimals ever displayed in these tables. Litigation, torture, foreclosure, you name it. Consequently, we built that behavior into this thing. “If you are a decimal, ye shall be smoted into an int”.
Queue the old timey Detective music. And then “She” came along.
You know how it is. You nail down the specs. You argue incessantly about “will we ever need this to be more flexible?” “Avaunt! and quit my sight!” And so it goes. You build it to spec, and then down the road, things change. And you end up in my shoes:
“Marc, what we really need, for this one table, for this one client, for just the first row, is that the decimals should appear. And here’s all the behavior around decimals”. When you’re dealing with Other People’s Money(tm), this stuff can get tricky.
Fortunately, this formatting business can all be nicely tucked away into the Formatter object and your calculation “engine” (engine means “a thing with a shitload of ‘if’ statements) can remain blissfully unaware of the unwholesome demands being placed upon its sanctity. Unfortunately, the TableBuilder looks like this:
drawTextFromMacro(textMacroName, formatter.formatWholeDollar(data[col],true,false), startX, startY, startAmountRightX);
See what it’s doing? Except in this one case, we don’t want that. In this one case, we want something different… we want a decimal amount in the cell, for one call to addTableRow(), in a TableBuilder whose reason for being is to print whole dollars.
Existing Solutions
Myriad approaches exist.
- Change the TableBuilder to not expect the data to be raw, but to instead expect the data to be formatted. This is perhaps acceptable if the TableBuilder didn’t also want to perform additional calculations on the incoming data. And so if we make this change, we must also change the input data to have those calcs done ahead of time. Small inconvenience, perhaps, but it does start to make the method signatures on this component get really hairy
- Accept a formatter object as an arg to the function that does the drawing. This would work, too, since CF enables dynamic method calls via CFINVOKE. But in order to do this, I’d need to pass the formatter object, the function to be called, and the arguments to that function. So now my method signature just ballooned by 3. Blech.
- Stop being lame with this “Formatter” object business, and create a different formatter for all the possible conditions I might encounter: WholeDollarFormatter, DecimalFormatter, PercentFormatter, and on and on. Then, I just construct an appropriate instance inside my loop that’s adding data, based on whether I need the row to be WholeDollar or Decimal Formatted, and pass it as an arg. All of the OO smarties right about now – who’ve gotten this far without wanting to go kick their cats b/c I’m so stupid for not having gone this route from day 1 – will probably say this is a good option. Yeah, probably.
- Add other approaches here. The internets love to make suggestions. So pretend I thought of all your suggestions, and pretend they’re here, in bullet point #4. :-)
- If your mind went to “FormatterStrategyFactory”, you need to go get yourself a beer
Where My Head Is
Lately, I’ve been thinking that maybe the strict OO that I have come to love isn’t all that hot. No, it’s not because some douchebag wrote a blog post about how he loves procedural CF and he can’t “get” OO. It’s more about how perhaps OO has run its course, and perhaps since the world is going multi-core, and parallelism is just the way things are, and since “state” is the root of all evil with respect to parallel computing, that maybe OO isn’t the best model in the new world. Enter stage left, Functional Programming. I’ve been doing a lot of javascript programming lately, dabbling in Groovy, and reading Programming in Scala. So somewhere in my brain, I have this ADD-raddled set of neurons that can’t get a moment’s peace, and as I hit this dumbass dollar formatting problem – and all I want to do is get to lunch, get through the day, and go the hell home – this thought pops into my head:

It kind of came unbidden. Up until that point, I had not done any serious investigation into closures, except what I knew about them from javascript. But it’s funny: in javascript, closures aren’t “a thing”. They are “the way things are”. It’s part of the language, like parentheses and colons and var and array.push(). If you’ve ever used jQuery or EXT, you’ve used closures and you maybe didn’t even know it.
All of this is to say that in my head, thanks to the fact that I can’t focus on one thing lately for more than a few hours, I had these other languages creeping in saying “If you were programming in ME, this is how we’d solve it and you’d be on your way out the door”.
I do not know if that is good or bad. Maybe it’s lazy? Maybe it’s impure?
But think about this: Wouldn’t it be sweet, if in my current position, I could tell my function: “Hey, Function, when you format this data, I want you to do it this way”
And maybe it would look like this:
tableBuilder.addTableRow(
data=someArray,
blah=whatever,
formatter="decimalFormatter"
);
And you’re thinking: “But dude, that looks exactly like what you described above, with the different Formatter classes, each with a single “format” method or whatever. But it’s not. Instead, formatter is a function, not an instance of a DecimalFormatter object I’ve declared elsewhere. That’s right, a function. And when tableBuilder does its drawText(), it does it like this:
drawTextFromMacro(textMacroName, formatter(data[col]), startX, startY, startAmountRightX);
What your CFML might look like if it had closures
You should be wondering: “How did he define this function? What does it look like?”. And here, in imaginary CF, is the answer:
decimalFormatter = function(value){Formatter.formatWholeDollar(value,true,false)};
tableBuilder.addTableRow(
data=someArray,
blah=whatever,
formatter="decimalFormatter"
);
What’s happening in this imaginary example is that I’m passing a function I’ve defined in “ThingThatUsesTableBuilder”, named it “decimalFormatter”, and passed that function into the tableBuilder.addTableRow() method. TableBuilder then calls that function as if it were some function inside of itself. It looks completely natural. But notice this: the call to the formatter(…) function has no idea about what that Formatter object is. It doesn’t know about its state. Hell, for all it knows, formatter() uses some other object to do its work. It doesn’t know, it doesn’t care. It just does it.
Another example: Maybe the call to addTableRow looks like this:
tableBuilder.addTableRow(
data=someArray,
blah=whatever,
formatter="function(value){Formatter.formatWholeDollar(value,true,false)}"
);
See that: it’s defining the function on the fly. It uses the “guts” from that Formatter object that I discussed way back at the beginning, passing some additional params to control its behavior. Then, when drawTextFromMacro() gets that function as the formatter, it knows what the “Formatter” object is (this is the magic of closures), and it applies that formatWholeDollar() function to the data.
Which brings us to….
What is a Closure?
I will get this wrong. I will miss the nuance and subtlety and beauty and power. That’s why you go find the answers yourself. So I’m going to give you my definition, based on a lot of reading and experimentation:
Closures are function literals + party invites.
Let’s talk about literals. Literals are the things on the right. y = 5; y is an int literal. you = “rad”; “rad” is a String literal. MXUnitHombres = {frameworkJunkie=”Bill”, mockMaster=”Bob”, pluginDude=”Marc”, residentGrump=”Adam”, seleniumGuru=”MikeH”, cohibaSupplier=”MikeR”} is a Struct literal.
decimalFormatter = function(value){…..} shows a function literal on the right.
tableBuilder.addTableRow(
data=someArray,
blah=whatever,
formatter="function(value){Formatter.formatWholeDollar(value,true,false)}"
);
shows a function literal, passed as an argument to some other function.
Party Invites: When you define your function literal, that function might do simple things to the incoming arguments and not need the support of any additional functions/objects/variables. In that case, the thing you define really isn’t a closure. It’s just a function. But when you need your function to “remember” things about the world in which it was defined – in my case, I want my function to “remember” what the Formatter object was – that’s were we get into closures. In my example above, where I created the decimalFormatter function, its contents included a reference to the Formatter object I created earlier. When I pass my function into other objects and functions, it will still work – even though the recipient of my function has no notion of this “Formatter” object. What I’ve done is I’ve invited the Formatter object to the party. I’ve said “Hey, you, you come along with me”.
At risk of offending the purity gods, I’ll say this. Think of it like if your function literal "kept knowing about all the variables you invited into it even after that function was passed into a place that had no knowledge of those variables”. Ben Nadel probably does as good a job as I’ve seen of graphically describing this, in the context of javascript.
So for example, look at that code up above, where I’m doing formatter=”function(value){Formatter.formatWholeDollar…}” as an argument to addTableRow(). In the refactored example, now that TableBuilder is no longer responsible for formatting, it doesn’t know anything about this Formatter object. It’s been relieved of that responsibility. How is it supposed to know what it means when it gets a function that calls this “Formatter.formatWholeDollar” thing? Well….
That’s closures. It knows about it because that’s how closures operate. They “enclose” or “close up” the stack around them and stuff em in a napsack and take it with them on their journey. They say to TableBuilder “tut tut, TableBuilder. Don’t fret. When you call me, I’m going to call this Formatter thing that I’ve got in me pocket, and ye shan’t worry, nor shall ye hurt him, because he’s mine and ye can’t keep him. So call me, I’ll do what I do, and go about yer business.”
Why is This Preferable?
In my case, this approach is preferable because it lets me very cleanly and easily encapsulate the behavior I want very close to the point at which I’ll use it. Immediately before I call the function that adds the row of data, I define the formatting it will use. Now… all the nastiness behind formatWholeDollar() is safely tucked away. We want that stuff out of the picture. We do want to control those last two args though (whatever they are) for the purpose of just this one row of data. So for this one row, we say “I want to call formatWholeDollar, with these two extra args”. And we do that by defining a function that does just that.
What’s it look like in real life?
As part of my foray into closures, I wanted to see what it’d feel like to do a rough approximation of my problem in some different languages. I chose the ones closest to me at the moment: javascript, groovy, and scala.
Here’s some javascript code that does kinda the same thing (stripped down for clarity). This is full HTML, so that muddies the picture somewhat, but I wanted to give you something you could copy/paste/run right in your browser. It defines a Formatter object, an array, a function that does stuff with the array and takes a formatter function. Then it defines two functions (dollarAdder and zeroAdder). In the HTML, the onClick attributes call the doStuffWithArray function, passing in the function.
<html>
<head>
<script>
//ignore... just for printing stuff to screen
function addRow(data){
var newline = document.createTextNode(data);
document.getElementById("content").appendChild(newline);
document.getElementById("content").appendChild(document.createElement('br'));
}
values = [1,2,3,4,5];
Formatter = new Object();
Formatter.formatWithOptions = function(value,addDollarSign,addTwoZeroes){
if(addDollarSign) value = '$' + value;
if(addTwoZeroes) value += '.00';
return value;
};
function doStuffWithArray(array,formatter){
addRow("Doing stuff with " + array);
for(var el in array){
addRow("Using item " + array[el] + " as " + formatter(array[el]) );
}
}
dollarAdder = function(value){return Formatter.formatWithOptions(value,true)};
zeroAdder = function(value){return Formatter.formatWithOptions(value,false,true)};
</script>
</head>
<body>
<input type="button" value="dollar adder" onclick="doStuffWithArray(values,dollarAdder);">
<input type="button" value="zero adder" onclick="doStuffWithArray(values,zeroAdder);">
<input type="button" value="inline dollar and zero adder" onclick="doStuffWithArray(values,function(value){return Formatter.formatWithOptions(value,true,true)});">
<div id="content"></div>
</body>
</html>
Run that, click the buttons, and you’ll see it in action.
Here’s some groovy:
package formatters;
class Formatter {
def formatWithOptions(Number value, boolean addDollarSign, boolean addTwoZeroes){
def newValue = value.toString()
if(addDollarSign) newValue = "\$" + newValue
if(addTwoZeroes) newValue += ".00"
return newValue
}
}
import formatters.Formatter
class Main {
static main(args) {
def formatter = new Formatter()
def values = [1,2,3,4,5]
def dollarFormatter = {formatter.formatWithOptions(it,true,false)}
def zeroFormatter = {formatter.formatWithOptions(it,false,true)}
def main = new Main()
main.doStuffWithList(values,dollarFormatter)
main.doStuffWithList(values,zeroFormatter)
main.doStuffWithList(values,{formatter.formatWithOptions(it,true,true)})
}
def doStuffWithList(list,fn){
println "Doing stuff with " + list
list.each {println "using item " + it + " as " + fn(it)}
println "Doing other stuff..."
}
}
Looks awfully similar to the javascript, doesn’t it? The main difference is groovy’s “it” keyword, as opposed to javascript where you can name your parameter whatever you like. The other difference is that I think this groovy example more clearly demonstrates the “Party Invite” concept. I’ve defined the “formatter” instance in the main method. I’ve defined the dollarFormatter and zeroFormatter function literals in main, using that formatter instance. I pass in those functions as arguments to another function (doStuffWithList), which lives in an instance of another object (because I’ve created a new “Main”), and that other function, in a new instance of Main, should by all reasoning have no notion of what “formatter.formatWithOptions….” means. But it does, because we’ve invited him to the party when we defined the function. This is why doStuffWithList doesn’t complain. In the javascript example, it very well might work because of the global nature of the “Formatter” I’ve declared. In this groovy example, it’s clearly shown that that is NOT happening.
And finally, some scala:
package formatters
object Formatter {
def formatWithOptions(value:Number, addDollarSign:Boolean, addTwoZeroes:Boolean):String = {
var newValue:String = value.toString()
if(addDollarSign) newValue = "$" + newValue
if(addTwoZeroes) newValue += ".00"
return newValue
}
}
package main
import formatters._;
object Main {
def main(args : Array[String]) : Unit = {
val values:List[Number] = List(1,2,3,4,5)
println (Formatter.formatWithOptions(values(1),true,false))
//formatter.formatWithOptions(value,true,false)
doStuffWithList(values,dollarFormatter)
doStuffWithList(values,zeroFormatter)
doStuffWithList(values, Formatter.formatWithOptions(_,true,true) );
}
def dollarFormatter = Formatter.formatWithOptions(_:Number,true,false)
def zeroFormatter = Formatter.formatWithOptions(_:Number,false,true)
def doStuffWithList(list:List[Number], fn:(Number) => String ) : Unit = {
println("Doing stuff with " + list)
for(item <- list) println ("using item " + item + " as " + fn(item))
println("Doing other stuff")
}
}
I’m least comfortable with Scala, so it’s most likely I’m A) doing it a little wrong, B) doing it all kinds of wrong, or C) doing all this in 20 lines when I could contrive some angle-bracket-dash-colon-underscore-ridden beast to do it in a single line of code. The two main differences here are that I had to define the formatter functions outside the place where I was using them (i.e. I couldn’t define the functions inline with the rest of the code, like I could with Groovy and Javascript, though that’s probably b/c I don’t know what I’m doing), and the use of “_” as the argument name. Think of it as like “it” for Groovy, but with symbols instead, because Scala is queer for symbols.
Final Thoughts
I included examples from other languages because I wanted to give you the feel of closures. I do not intend to come across as one of those people who wants things in CF just because the cool kids have them. Still… I like closures, a lot, and I believe that if they were added to CFML, in time many programmers would look back on the days before closures and think “Remember them days, Buck?” “Yeah, Grady. Them days sucked.” Closures add a level of convenience that will be shown to exceed even the convenience of struct and array literals added in CF8.
The risk with closures is that it can invite a return to spaghetti, with large chunks of functionality stuck in-line. This is a Bad Thing(tm) and good programmers would be wise to avoid this trap. You’ll notice in my examples that I used closures more as a tidying-up. In fact, these examples show no original functionality. This is particularly important for testability. I trust that Formatter.formatWithOptions(value,true,false) and …(value,true,true) and …(value) all work correctly because they’ve all been unit tested. I do not care to test the closure I’ve defined because all it does is call functions on other objects. If CFML ever gets closures, you’ll start seeing all manner of bloggers railing against The Monster Closure. It will be good advice, so heed it.
I am most certainly not the first person to want Closures in CFML. One of my favorite CF dudes has been talking about it for a while, and Sean Corfield told me that he planned to formally submit a recommendation to the CFML Advisory Committee. CF makes things easier, and I’d like to hear your thoughts on how you might or might not use this feature were it added.
Finally, I welcome any comments, criticisms, dialog, corrections, clarifications, etc. This was a “journey” of sorts for me. I used it to learn a lot more than I knew before, but surely I’ve gotten things wrong and so I’ll gladly correct any misinformation.
--Marc