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