Anonymous Recursive Functions

Posted in: javascript
I learned this "trick" some time ago, while reading the source code for the MooTools JavaScript framework (version 1.1, I think). I used this "trick" not so long ago, when developing the Spacetree visualization for the JavaScript InfoVis Toolkit library. When clicking a node, the Spacetree visualization unselects all tree nodes and then selects the nodes in between the root node and the selected node. This can be implemented as a recursive function, since we have to iterate through the clicked node and its ancestors to set those nodes as selected. I defined an anonymous recursive function that receives a node and a special value as formal parameters, and sets the selected property from this node and its ancestors to the specified value:
(function(node, val) {
      if(node == null) return;
      node.selected = val;
      return arguments.callee(node.parent, val);
  })
*arguments.callee* holds a reference to the defined function. You can check that by copying this code:
(function(text) {
    alert(arguments.callee);
    alert(text);
  })("some text");
and running it in your Firefox console. Unfortunately, our anonymous recursive function needs to be called more than once, since we first need to unselect previous selected nodes, and then to select the nodes in between the clicked node and the root node. Similar to the "return this" trick to chain method calls, we can add "return arguments.callee" to chain function calls.
(function(node, val) {
      if(node == null) return arguments.callee;
      node.selected = val;
      return arguments.callee(node.parent, val);
  })
This way, we can call our function multiple times. I'll first pass the previous clicked node in order to unselect the previous selected path, and then I'll pass the new clicked node in order to select our new path:
(function(node, val) {
      if(node == null) return arguments.callee;
      node.selected = val;
      return arguments.callee(node.parent, val);
  })(nodePrev, false)(nodeNew, true);
What's more interesting though, it's trying to do the same thing in another language, like Lisp or OCaml. Who knows, you might sumble upon the Y combinator.
Comments
blog comments powered by Disqus