Tuesday, February 26, 2008

shorter lambdas

In a stunning illustration of the bikeshed principle, Arc's feature that got the most attention and praises has been its short notation for anonymous functions: "[foo _]" is equivalent to "(fn (_) (foo _))". Since I'm in an experimental mood these days, let's give it a try, as it's merely a one-liner.
Using "[...]" to mark the function's boundaries wouldn't be a great idea,
as it would cause ambiguities in table constructors, and when used at the beginning of a statement, might be agregated to the previous statement as an `Index accessor. Instead, I'll use a prefix antislash; there's no need for a closing marker: in Lua, the end of an expression can be determined implicitly. Here's the meta-code, to put directly in the file where the notation is to be used:
-{ mlp.expr.prefix:add{ '\\', prec=5, builder=|_,x| +{|_|-{x}} } }
It can be used, for instance, as:
table.foreach (mlp, \print('key:', _))
I chose to give it a very low precedence, this is what seemed the most sensible. When you're not happy with this, use parentheses.
What good is that extension? It can be used instead of the already short "|_| foo(_)" notation; it saves two characters, and its usage is restricted to single parameter functions; so in terms of code shortening, it only makes sense for the tiniest functions. The most decent example I could think of is "\_[1]" to extract the first element of a list.
Clearly this has no interest in terms of saving tokens nor AST nodes, yet I can't help but finding this notation rather likeable. Maybe it has some auto-documentary mojo in it? By not even bothering to give a name to the parameter of a tiny function, we give it some sort of point-free flavor: "\_[1]" is read as: "[1] as a function", rather than "the function that takes '_' and returns '_[1]'".
It would also look nice in "\_+1"; in short, it seems to have a role equivalent to Haskell's sections, which allow to write "(+)" instead of "|x,y| x+y", "(+1)" instead of "|x| x+1", "(1+)" instead of "|x| 1+x" etc. In any case, the notation seems to only make sense in very functional code. It should be tried next time I have an occasion...