[fpc-devel] Delphi anonymous methods

Vasiliy Kevroletin kevroletin at gmail.com
Sun Mar 3 02:43:52 CET 2013


> === output end ===
>
> But if I've understood you correctly I'll get the following instead:
>
> === output begin ===
>
> 21
> 21
>
> === output end ===
>
Right
You want to capture variable by value. For example lambdas in c++ have 
special syntax to choose how to capture. By reference or by value. 
Capturing by value is useful to make parametrized anonymous functions. 
Capturing by reference is useful to change local variables. In other 
c-like languages if you have capturing by reference you can simply 
simulate capturing by value. You can wrap anonymous function into a 
block and declare local variable in this block.

Example:
=== begin perl ===

for my $i (0 .. 9)
{
     my $copy = $i;
     $f[$i] = sub {
         printf($copy);
     };
}

$f[0]->(); #0
$f[9]->(); #9

=== end perl ===

Javascript is more like Delphi. Scope of variable in javascript 
restricted by entire declaring function not by declaring block. So you 
should do something like this:

=== begin javascript ===

for (i = 0; i < 10; ++i)
{
     (function () {
         var copy = i;
         f[i] = function () {
             alert(copy);
         }
     })()
}

f[0]();
f[9]();

for (i = 0; i < 10; ++i)
{
     (function () {
         var copy = i;
         f[i] = function () {
             alert(copy);
         }
     })()
}

f[0](); // 0
f[9](); // 9

=== end javascript ===

for (i = 0; i < 10; ++i)
{
     (function () {
         var copy = i;
         f[i] = function () {
             alert(copy);
         }
     })()
}

f[0]();
f[9]();


>
> You also wrote that local variables seem to be located on the 
> FrameObject. So how is it with multi threading? E.g. 
I missed test with multithreading and made wrong assumption.

Sven's test:
=== test begin ===

   for i := 0 to 1 do
     TThread.CreateAnonymousThread(
       procedure
       var
         x: LongInt;
       begin
         Writeln('Address ', TThread.CurrentThread.ThreadID, ': 0x', 
IntToHex(Integer(@x), 8));
         x := Round(Random*100);
         Writeln('Before ', TThread.CurrentThread.ThreadID, ': ', x);
         Sleep(5000);
         Writeln('After ', TThread.CurrentThread.ThreadID, ': ', x);
       end).Start;

=== test end ===

=== output begin ===

Address 2028: 0x00F3FF68
Before 2028: 0
Address 2176: 0x0103FF68
Before 2176: 3
After 2028: 0
After 2176: 3

=== output end ====

There are different local variables in different threads. But in one 
thread local variables are same.

=== test begin ===

   for i := 0 to 1 do
     f[i] :=  procedure
              var x: Integer;
              begin
                Writeln('Address ', TThread.CurrentThread.ThreadID, ': 0x',
                        IntToHex(Integer(@x), 8));
              end;
   Writeln(' ');
   for i := 0 to 1 do
     f[i]();

=== test end ===

=== output begin ===

Address 3364: 0x0012FF98
Address 3364: 0x0012FF98

=== output end ===

Do you have any ideas how and why such behaviour implemented ?

Vasiliy K.






More information about the fpc-devel mailing list