LDEV-250: lambdas are not closures

G’day:
I think this ticket warrants further discussion: https://luceeserver.atlassian.net/browse/LDEV-250

My personal opinion is that the syntactical difference here shouldn’t vary the way things work, and these two should be functionally the same:

f =function(x,y){
 return x+y
}

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

Obviously I’m not using closure here, so it’s a poor example, but the point is that they’re both function expression syntaxes, as opposed to function statement syntax:

function f(x,y){
 return x+y
}

That said… are there precedents in other languages that:

  1. they have more than one syntax for anonymous functions to start with;
  2. if they do, then the two syntaxes vary in regards to how
    the bind variables.

I am not saying we need to follow precedents (one way or the other) from other languages, but I think there should be a good reason to depart from how it’s done elsewhere if there is an established precedent.

Thoughts?


Adam

The only thing I could think of (and its relatively weak I admit), is that given the shorter syntax, one would assume it to be more lightweight than a closure function expression. That is, closures can easily produce memory leaks if not cleaned up properly (thinking only from JS side here, though I would imagine such would be the case in Lucee as well), whereas if lambdas are not closures, they do not trap objects in memory.

the lambda function have the same behaviour as regular UDF, but I have to agree with Adam on this.

We have a base rule, the chosen syntax should not have influence on the environment. So inline function is inline function independent of the syntax used, they should work the same way.

I’m pretty sure the original motivation for this is that someone had tried to use function-expression syntax to create a function which they then injected into an object to try to access the variables scope (or private methods, or something), and they were flummoxed that this would not work.

Then someone from the Railo / Lucee (I dunno how long ago this was, nor which person it was) suggested the pending “lambda” syntax could not use closure, to accommodate this requirement.

In reality the guidance here ought to have been “nah, you can’t do that; just use a function statement instead to define the function if you want to do that: that already works the way you want, and function expressions are supposed to use closure. That’s what they’re for”.

Myself and a coupla others did express - at the time - that it was a bad suggestion. It looks like that position might be getting some weight behind it now.

One thing I thought to be “inclusive” in our solutions here is to vary PHP’s approach to doing closure, which is along these lines (sorry for the retinal scarring you’ll get from looking at $P_H__p code):

$someVarToBindTo = 'foo';
$someVarToNotBindTo = 'moo';

$f = function() use ($someVarToBindTo) {
    // can use $someVarToBindTo
    // cannot use $someVarToNotBindTo
};

Now I’m not suggesting that. But perhaps this:

someVarToBindTo = "foo"
someVarToNotBindTo = "moo"

f = function() lateBind (someVarToNotBindTo) {
    // can use someVarToBindTo as per usual closure rules
    // someVarToNotBindTo is not bound yet
}

// some other context, later on
someVarToNotBindTo = "goo"
result = f() // *now* someVarToNotBindTo is bound, and it sees the one in this context (with value "goo")

I hasten to add I don’t see the need for this. If you want closure, use a function expression. If you don’t, use a function statement. That’s all we need.


Adam

1 Like

OK, so you’ll be changing the behaviour of arrow functions then, in line with https://luceeserver.atlassian.net/browse/LDEV-250 ?

Nice one.


Adam