Mark said:
You aren't the only one who thinks that closures are unnecessary.
Dave McQuigg has posted several messages today making that
argument. I also have several people saying they couldn't live
without them. One javascript programmer says he uses instance
variables for access outside of objects (properties) and closure
variables for storage variables inside objects. He has posted a
lengthy messge about it on the Prothon lists. Go figure.
I'm the JavaScript programmer.
I would never say I couldn't live without closures--I don't think I've seen
a situation where they are the only way to get the job done. But I do find
that they provide a very clean and natural way to do some things.
One problem with talking about closures is that silly counter example that
we all come up with when we need to demonstrate their use. Even closure fans
like me use that same example for some reason--it must be a law or
something. The trouble with that example is that there's not really much
benefit to the closure there. (Just an observation: The arguments I'm seeing
against closures are coming from people who haven't used them in situations
where they are beneficial.)
One place I've been finding closures to be a clean, elegant solution is in
Acrobat multimedia JavaScript code, especially in event listener methods. I
developed the multimedia JavaScript API in Acrobat 6, and naturally I had to
eat my own dog food and develop a number of sample multimedia PDF files.
(You can find one of them at
www.mfiles.co.uk - scroll down to the Animated
PDF Sheet Music section.)
Here is some Acrobat multimedia code written with and without closures.
(Sorry to use JavaScript as an example, but I don't have any real life
Python or Prothon code with closures handy. This should serve to illustrate
the concept, though.)
We'll define a function "reportScriptEvents( reporter )" which plays a media
clip and listens for any Script events that the media clip fires. It
accumulates the text of those Script events in a log string, and when the
player closes, it calls the 'reporter' function and passes it that string.
This is done using event listener methods which are called during
playback--after reportScriptEvents returns.
Here is the reportScriptEvents function and a testReport function which
provides a reporter that pops up a message box when the player closes:
function reportScriptEvents( reporter )
{
var log = "";
app.media.openPlayer(
{
events:
{
onScript: function( e )
{
log += e.media.command + ': ' + e.media.param + '\n';
},
afterClose: function()
{
reporter( log );
},
},
});
}
function testReport( title )
{
reportScriptEvents( function( log )
{
app.alert({ cTitle: title, cMsg: log });
});
}
testReport( 'Here are the script events' );
To me this is very clean and simple. I don't have to think about the fact
that the onScript and afterClose functions are called long after
reportScriptEvents returns, or the fact that the anonymous reporter function
inside testReport is called after testReport returns. I don't have to create
an object or any kind of machinery to hold these persistent variables. They
just work.
As an alternative without the closures, I can take advantage of the fact
that we pass the media player object into the event methods:
function reportScriptEvents( reporter )
{
var player = app.media.createPlayer();
player.myLog = "";
player.myReporter = reporter;
player.events.add(
{
onScript: function( e )
{
e.media.player.myLog +=
e.media.command + ': ' + e.media.param + '\n';
},
afterClose: function( e )
{
e.media.player.myReporter( e.media.player.myLog );
},
});
player.open();
}
This is quite a bit messier. I have to know more about the details of what
Acrobat passes into event listeners (the e.media.player.* business). And I
still have to come up with something to substitute for the closure in the
testReport function.
Maybe there is a more elegant solution, but it's past midnight and the
margin of my brain is too small to contain it. Closures make this kind of
code so simple that I can understand it even at this late hour.
-Mike