At work today, I was trying to get a certain function to work properly… the function’s function (heh) was to take a button, a DataGrid, and a number indicating a column of the DataGrid that contains boolean values (meant to indicate whether the row is “selected” – this was being used in tandem with a CellRenderer containing a CheckBox allowing the user to select/deselect multiple rows) and cause a click of the button to perform a certain operation (namely, calling a remoting method to delete them from their database, using the value of another field as the key) on the records for which that field’s value was true (i.e. their checkboxes were checked). Oh, but only if the user confirms the action by clicking Yes in an Alert box after clicking the button. Not so bad, right?
Tricky, however. This involves setting a function-typed property of the button (onRelease) to the function you want run when the button is clicked (or more precisely, when the mouse button is released after clicking the button); the remoting method needed to also be specified (as either an argument, or defaulting to a reference to a method on the object), since I meant this to be used on multiple DataGrids in the application that viewed data from various different parts of the database that had different remote methods to deal with them – so I also required a function that returned the PendingCall returned by the appropriate remote method. Remoting PendingCalls also require two functions to be given to them, via an object called a RelayResponder, to specify the callback functions for success and failure – but these are only given by their string name (so they have to be named, class-level functions).
This much I had already accomplished a couple weeks ago – what I was trying to do today was to add the alert box to confirm the operation. An Alert is displayed by calling the static method show() on the Alert class with arguments specifying things like what buttons, title, and so on as well as a “handler” function or object, which Alert basically makes an EventListener, that is run when one of the buttons on the Alert is clicked. Until you get into that handler function, you really don’t know whether the user clicked Yes or No.
So yeah, there’s a lot of functions being thrown around here, but nothing too crazy for someone who’s had a little bit of introduction to functional programming. ActionScript is hardly functional programming, but functions are a first-order object in it, and many libraries and components exploit this fact. So here I was inside a superclass function that sets up this “delete-selected” button – which calls a function that has to pass a function to a function that shows an Alert box, and that function itself has to call another function that is defined in this set-up function.
My co-worker Judah thinks that nested functions are evil. I say he’s wrong, and that functions are the very essence of programming, and “nesting” them (using functions within other functions, and so on) magnifies their power exponentially, and I would even go so far as to say that in some modern programming situations there’s things you really can’t do very well (if at all) without them. But if you can find a good way to do what I just described without nesting some “anonymous” in-place functions with lexical closures, (particularly given the use of library functions that ask for functions as arguments without letting you pass your own arguments to those), then by golly post it in the comments section please.
It’s not hard to understand however, why this pretty talented Flash developer and right decent chap that I work with might have an aversion to this kind of use of functions. I think we can lay aside his lack of a formal CS college education, as he’s a pretty bright and very experienced guy, and there’s nonetheless plenty of people walking around with CS degrees who have a hard time wrapping their head around the idea of functions doing things to/with functions. There’s a more concrete reason, and that is that lexical scoping in ActionScript doesn’t really work the way people with prior experience in certain programming languages would expect. Functions defined within class-level functions have a way of losing their ability to access class-level members (be those variables or functions). I’m not sure if the general consensus is that this is a bug, but it’s my opinion, and I think Judah’s as well, that it is. Maybe ActionScript 2.0 is supposed to be using some other kind of scoping, but I think that such would be a departure from the ECMAScript specification from which it’s supposedly derived.
The idiomatic workaround is to use a class called Delegate. Delegate has basically one method (that anyone uses at least) called “create”, which, given a function and an object, returns a Function (capitalized to reflect the fact that the expression does indeed return an object of type Function) that is like the argument function, except set up to run in the scope of the object given. Reaction to any scope-related issue in ActionScript has become almost knee-jerk use of Delegate, to the point that code is littered with Delegate.create(this, …); – personally, I think anytime you have to wrap your code in an extra function to remind it to use the enclosing object (“this”) as its scope, something’s wrong. But then, lexical scoping is about the only scoping I know, other than Common Lisp’s dynamic variables. Anyway, it’s to the point where people have adopted a “just Delegate everything” policy, which means often it’s used where it isn’t necessary. I’m not sure how much unnecessary overhead this creates – probably not much – but I submit that it makes for some unnecessary wear on the ol’ fingers.
The other way of dealing with the issue is a very anti-“nested function” attitude; Flash coder forums are full of people claiming that defining a function literal within a class function is a “memory waste” and “bad form.” True, it can result in memory waste depending on how you use it – but what Flash developers decry as “bad form,” I claim is nothing more than that perfectly normal and very common thing called a closure (classes themselves are closures – your class methods reference variables that are declared outside the functions themselves, but within the class that encloses them), and the “wasted” memory is in fact, memory containing data you intend to use within the inner function. At least it should be – or else you probably don’t have sufficient cause to be using a “nested” literal function.
For an example of what I claim to be a good and proper use of “nested,” or literal, or anonymous, or in-place, functions (I should realy settle on a term), see my earlier post of the numeric DataGrid sorter. It creates a function whose job is to be a listener for the DataGrid’s headerRelease event. Of course the activation object of useNumericSort() persists as attached to that listener function – the listener function needs it because it contains the columns array. I go yet another level too – one of the arguments to the sort() method on the Array class is a comparison function, and since the elements to be compared in this case are rows of a dataProvider, that function needs know the column name corresponding to the column being sorted on, and the only place it can get that data is from the listener function inside which the comparison function is being defined. Sure, if you called this function a hundred times you’d have a whole bunch of these extra activation objects… but the purpose of useNumericSort() is to be called exactly once for each DataGrid you want numeric sorting to work on – and in many cases like this one where you’re assigning a function to one of those “on” properties, the new listener function will replace the old one, which, no longer having anything referencing it, will get garbage-collected. (That’s currently not the case with my DataGrid sorter, since it uses addEventListener, but it may be possible to fix it so that it is.) Now, if you actually need it on a hundred DataGrids, then by all means call this function a hundred times – but don’t claim that the extra memory taken up by the persistent activation objects is wasted – it’s being used!
Furthermore, I believe that the “no nested functions” policy results in considerable loss of flexibility in your programming. It prevents you from writing reusable code that solves general problems, and instead forces your code to be geared (hard-coded?) to the project-specific instance of a general problem – such that if you want to use the same technique again, you have to re-hack it to each specific case; exactly the kind of error-prone busy-work that object orientation was supposed to free us from. In other words, I’d be stuck rewriting useNumericSort() and/or the un-nested functions it uses, with a few lines changed slightly, each time I wanted a DataGrid to have numeric sorting. As written, I just paste it in, call it with the right arguments, and it should work.
So, to sum up for any Flash coders not wanting to bother with such hokey academic Comp Sci concepts as lexical closures, there is clearly a type of case where the so-called “nested function” is appropriate, and perhaps arguably necessary: when you need the inner function to be “customized” in some way according to data whose scope is the outer function (especially its arguments).
Anyway, back to the story. I had to pass the function that makes the remoting call (by calling another function that specifies just what remoting call that is) to Alert.show() as the handler function. And it turned out that, being three or four functions deep, suddenly the function that actually makes the specific remoting call annoyingly forgot an important class-level variable that it needed to send along to the remote method, unless everything was Delegated to “this” all the way down. Problem was that, the function that made the remoting call and returned its resulting PendingCall also needed to accept an argument: the keys identifying the records to be deleted.
I was beside myself trying to figure out how to get this done – pass a function to Delegate but also run it with arguments– while another co-worker, Andrew, the guy responsible for all the server-side PHP I was using via Flash Remoting, was sitting next to me trying to help me out, and it occured to me to try something as a joke that I thought I would amuse him. I stuck a pair of parentheses (which I now realize may not have been necessary) around the call to Delegate.create and placed the argument list right after it. “See, here’s the function, and here’s the arguments!” Grinning, Andrew replied that if this worked, it would take the “Weird prize” from C.
Of course, it’s not hard to justify its working – the Delgate.create call does after all return/evaluate-to a function, and when you put a parenthesized argument-list after a function name, you’re supposedly calling the function. Replace “function name” with just “function,” thus implicitly including any expression that evaluates to a function, and it makes perfect sense. It’s just that I was surprised that ActionScript, a language that had yet to get lexical scoping quite right, would sport a parser that would do something that cool. And there are plenty of well-respected languages that, for whatever reason, wouldn’t allow such a thing to go on. But then again, ActionScript is the first non-functional language I’ve worked in that treats functions as first-order data.
Here’s where the “dangerous” part comes in… allegedly this “scope bug” is going to be fixed in the next version of ActionScript (3.0). If that happens, it would effectively break the last barrier to me writing ActionScript code structured like Lisp code – slipping in-place, single-use functions into argument lists, and generally turning the whole structure of my ActionScript coding inside out. And I could thus be in danger of making future, less Lisp-aware maintainers of my code very aggravated with me if I let myself take such a capability to its logical conclusion. ;-)
Okay, so that probably wouldn’t really happen. But it’s tantalizing to think about being able to write ActionScript that way.