Hi Folks,
For the script optimization/compilation work I’ve been doing, I’ve been looking into what it will take to compile lambdas (anonymous functions). Currently, these use “reference” semantics when referring to local variables. For example, this code:
function demo(): function()
{
local i = 3;
local f = function() { print i; };
i = 5;
return f;
}
event zeek_init()
{
demo()();
}
will print 5
, because the anonymous function assigned to f
holds a reference to demo
’s local variable i
, so reflects the change made to i
after the instantiation of the anonymous function. This continues to work even after demo
exits (which requires some extra work internally to support).
Due to how the script compiler represents values, the above semantics would require some fairly extensive support.
My proposal is to change the semantics to instead be shallow-copying, which means that atomic values are copied, but aggregate values (tables, records, and vectors) are shared. With this change, the above code would print 3
. However, this code would still print 5
:
function demo(): function()
{
local r: record { i: count; };
r$i = 3;
local f = function() { print r$i; };
r$i = 5;
return f;
}
event zeek_init()
{
demo()();
}
This change also brings the functionality closer to that used in when
blocks, which use deep-copying. (Arguably, it could be a good idea to change when
to use shallow-copying, too, but that’s a different discussion.) If one wants deep-copy semantics, that can be done with explicit copy()
s, like this:
function demo(): function()
{
local r: record { i: count; };
r$i = 3;
local r2 = copy(r);
local f = function() { print r2$i; };
r$i = 5;
return f;
}
event zeek_init()
{
demo()();
}
— Vern