Want direct capture of nested procedure/function into a reference to procedure/function to work (for anonymous procedures/functions)
Summary
- Indirect capture of a nested procedure works, direct capture does not always work.
- Would like equal capture of everything in the parent/containing scope.
System Information
- Operating system: Linux, FreeBSD (but should work for All)
- Processor architecture: x86-64, AARCH64 (but should work on All)
- Device: Computer (but should work on all)
Example Project
This does not work, a direct capture of nested procedure.
{$mode delphi}
{$modeswitch anonymousfunctions}
{$modeswitch functionreferences}
program nocapture;
type
tSimpleProc = reference to procedure;
procedure main;
var
tcf: tSimpleProc;
x: integer;
procedure nested;
begin
writeln ('Hello from nested! x: ', x);
inc(x);
end;
begin
x := 100;
tcf := procedure begin nested; end;
tcf();
tcf();
end;
begin
main;
end.
The above results in:
Free Pascal Compiler version 3.3.1 [2022/09/26] for x86_64
Copyright (c) 1993-2022 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling src/nocapture.pas
nocapture.pas(25,28) Error: Symbol "nested" can not be captured
nocapture.pas(34) Fatal: There were 1 errors compiling module, stopping
Fatal: Compilation aborted
Error: /home/shared-development/fpc_usr/lib/fpc/3.3.1/ppcx64 returned an error exitcode
This does work, example includes indirect capture to get the nested procedure to be captured.
{$mode delphi}
{$modeswitch anonymousfunctions}
{$modeswitch functionreferences}
program doescapture;
type
tSimpleProc = reference to procedure(const n: integer);
procedure main0;
var
tcf: tSimpleProc;
tcf2: tSimpleProc;
x: integer;
procedure nested(const n: integer);
begin
writeln ('Hello from nested! ', n, ' x: ', x);
inc(x);
end;
begin
tcf := nested;
x := 100;
procedure(const aArg: String) begin Writeln(aArg); end('Hello World');
procedure begin nested(1); end();
tcf2 := procedure(const n: integer) begin tcf(n); end;
tcf2(2);
end;
procedure main1;
var
x: integer;
begin
x := 132;
procedure begin writeln ('x = ', x) end();
end;
begin
main0;
main1;
end.
Produces this output:
Hello World
Hello from nested! 1 x: 100
Hello from nested! 2 x: 101
x = 132
Relevant background information
See Strange capture denial and acceptance for Anonymous Functions and Function refs on the Lazarus forums.