Hi all,
I’m sometimes annoyed by the trampoline garbage that results when referencing
variables in the surrounding scope from a lambda function (“closure”). Also,
all variables in the frame referenced by the lambda will be kept around, even
if just a single one is actually used in the lambda.
void foo()
{
string var1;
mapping var2;
string bar = “whatever";
function f = lambda(string arg)
{
write("%O, %O\n", bar, arg);
};
… other code that prevents tail-call optimization ...
return f;
}
int main(int argc, array argv)
{
function f = foo();
f(“gazonk”);
f = 0;
// The lambda and the variables referenced in the frame used to execute “foo”
are now garbage.
}
A possible workaround is to cut the reference to the “foo” frame:
function f = lambda(string var1, string var2)
{
return lambda(string arg)
{
write("%O, %O, %O\n”, var1, var2, arg);
};
}(var1, var2);
However, this is pretty verbose. Maybe it would make sense to introduce some
kind of syntactic sugar, for example:
lambda[var1, var2](string arg)
{
};
This could perhaps translate to the construct above, and I think this syntax
would map pretty well to how explicitly captured variables work in other
languages. Some languages allow renaming of captured variables – not sure if
it’s necessary or not. "lambda[myvar1 = var1, myvar2 = var2]() {}" or something.
Ideally, variables from the surrounding scope not present in the capture list
should not be usable in the lambda, to avoid unintended trampolines. Obviously,
this would follow the same pass-by-value/pass-by-reference semantics of the
various Pike types as in function arguments, which I personally think is a good
thing. (A special case would be "lambda[](string arg) { }” which would prevent
referencing any variables from surrounding scopes at all.)
What do you all think?
/Marty