Monday, 9 June 2014

CFML enhancement: alternate function expression syntax; "lambda expressions"

In this article I just want to - hopefully - extend the audience of a conversation taking place on the Railo Google Group ("Railo 5 lambda expressions"). Even if you're a ColdFusion developer (ie: only use the Adobe product, not the Railo one), this will still be relevant to you as Railo generally leads CFML development these days, so innovations they make will - perhaps some time in 2016 - make it into ColdFusion's dialect of CFML.

There are a lot of good brains in the CFML community, and I hope to encourage some more of them to join this discussion.

In Railo 5, Railo will be adding "lambda expressions" to CFML. The term "lambda expression" is analogous to "function expression", and the differentiation Railo are making here between long-hand function expressions and this new shorthand syntax is mostly an artificial one. A lambda expression is a function expression, and as far as I can tell does not make a distinction between the implementation's syntax. A lambda is basically just an anonymous function.  We're already got those in CFML (Railo and ColdFusion both), eg:

adder = function(x,y){
    return x+y

That's a lambda. So here's the first issue that could perhaps benefit from discussion: semantics. I don't think Railo's semantics here are correct. Oh, here's what Railo mean by when they use the term "lambda"... an alternative syntax for the above:

adder = (x,y)->{x+y}

That was taken from RAILO-2874, and I am not sure if that is definitely the syntax they'll be running with, but that's neither really here nor there: it's just that the syntax is slightly more terse: we don't specify the word "function" and the returned value is simply the value of the last expression in the code block. There's that arrow thing to indicate that the arguments (in parentheses) are passed to the block following it. Oh, I also suspect if the function's code is a single statement, we could dispense with the braces too:

adder = (x,y)-> x+y

So far, so good. Basically this shorthand syntax is akin to struct- / array-literal notation, compared to the long-hand version of declaring a struct or array with structNew() or arrayNew().

Ruby makes the distinction between long-hand lambda syntax and short-hand by calling the short-hand syntax "stabby lambdas". For the love of god, can we please just take that as "FYI only", and I am not suggestion such a stupid term be used to differentiate the two. More formally they use the term "lambda literal", which makes more sense. Perhaps Railo should use this terminology, but stick with existing terminology for function expressions, and run with "function literal".

This is where a slightly contentious situation comes in.

Micha from Railo contends that as well as being syntactically different, these lambda-expression-defined functions will also process differently: standard function expressions employ closure (ie: they're "closures", if you must), whereas function expressions using lambda syntax will not implement closure.

I don't think this is correct behaviour. Well... kinda.

Another issue came up a week or so ago when the notion came up that perhaps it ought to be possible to specify whether a function expression uses closure or not (my comment on RAILO-3099), eg:

myfunction = function() closure=false {
    // stuff not using closure

I asked Sean about this - he knows an awful lot about language design - and initially he was against it, but now when discussing this lambda issue, he seems to have kinda warmed to the idea in a tangential way:

Now... I've been combining the two concepts in my head, overnight. I think there's the case that Sean makes that there's a reasonable requirement for non-closure anonymous function expressions, but I think his suggestion might not be the better approach here. I think perhaps the shorthand syntax should simply create a normal function expression, and one that employs closure. And if one wants a function expression which doesn't employ closure, use a long-hand function expression, with the closure=false annotation as per above.

This sits better with me as it doesn't make what seems like a weird distinction between two different syntaxes designed to do the same thing, but augments the longer of the two syntaxes (which already has the capability to have these annotations? Dunno, actually!) to be extended via further annotation. This is roughly analogous to how one can specify different sorts of struct with structNew() (in Railo, anyhow), but a struct literal only creates a bog-standard struct.

So that's the scene. I guess my questions here are:

  1. I think Railo need to clarify their usage of the term "lambda" as they don't - to me - quite seem to be using it right?
  2. Is it legit to have the short-hand syntax create functions which behave differently to the long-hand syntax?
  3. Is it legit to have a function expression's usage of closure to be toggle-able?