So the outer anonymous function is essentially useless.
I do not think so. This would be useless:
procedure(var i,j,k:integer)
begin
Queue(procedure begin Sleep(500); Writeln(i,' ',hexstr(@i),' ',j,' ',k);end);
end(i,j,k);
inc(i);
.......
This captures the variables by reference.
Lets assume
i is zero.
The inner procedure is
queued (not synchronized), this means the inner procedure is executed in the main thread. It will wait for 500ms, but the child thread will go on without delay.
If the thread increments
i after 250 ms, this routine will print
i as 1.
This routine captures the values, not the references.
procedure(i,j,k:integer)
begin
Queue(procedure begin Sleep(500); Writeln(i,' ',hexstr(@i),' ',j,' ',k);end);
end(i,j,k);
inc(i);
.......
If
i is incremented after 250ms this procedure will still print
0 and not
1, because it captures the momentary values of the variables and not the addresses of the variables.
My experiments have shown this, I tested it.
Please consider, the outer procedure is executed in the context of the (child) thread, but the inner procedure is executed asynchronously and delayed in the context of the main GUI thread.
It is however better to use not the same shadowing variable names in the anonymous procedure, because this confuses the debugger apparently. It will always display the outer variable, not the inner.
(The compiler is not confused about this, but the debugger is)
So this is better, but has the same functionality:
procedure(i2,j2,k2:integer)
begin
Queue(procedure begin Sleep(500); Writeln(i2,' ',hexstr(@i2),' ',j2,' ',k2);end);
end(i,j,k);
BTW, Delphi does not support this construct.
Due to inline variables and constants and type inference you can write this in Delphi:
const pp= procedure(i2,j2,k2:integer)
begin
Queue(procedure begin Sleep(500); Writeln(i2,' ',hexstr(@i2),' ',j2,' ',k2);end);
end;
pp(i,j,k);
I have yet to find out if it can capture by value in the same way.
This is very useful if a anonymous procedure is called with time delay or from another thread.