Anonymous methods – variable capture versus value capture

Variable capture vs value capture is simple enough. Let us suppose that two anonymous methods capture the same variable. Like this:

Type
  TMyProc = reference to procedure;
var
  i: Integer;
  P1, P2: TMyProc;
....
i := 0;
P1 := procedure begin Writeln(i); inc(i); end;
P2 := procedure begin Writeln(i); inc(i); end;
P1();
P2();
Writeln(i);

There is a single variable that is captured by both methods. The output is:

0
1
2

This is capture of a variable. If the value was captured, which it isn’t, one might imagine that the two methods would have separate variables that both started with value 0. And both functions might output 0.

In your example, you are supposed to imagine that P1 captures the value 41, and P2 captures the value 665. But that does not happen. There is exactly one variable. It is shared between the procedure that declares it, and the anonymous methods that capture it. It lives as long as all parties that share it live. Modifications to the variable made by one party are seen by all others because there is exactly one variable.


So, it is not possible to capture a value. To get behaviour that feels like that you need to copy a value to a new variable, and capture that new variable. That can be done with, for instance, a parameter.

function CaptureCopy(Value: Integer): TMyProc;
begin
  Result := procedure begin Writeln(Value); end;
end;

...
P3 := CaptureCopy(i);

This will copy the value of i into a new variable, the procedure parameter, and capture that. Subsequent changes to i have no influence on P3 because the captured variable is local to P3.

Leave a Comment