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

Reply via email to