The future of lambda delegates

nobody nobody at mailinator.com
Thu Aug 17 11:20:25 PDT 2006


Bruno Medeiros wrote:
> nobody wrote:
>> Mikola Lysenko wrote:
>>
>>> Recent D releases (notably 0.161) have updated the syntax and 
>>> improved the overall usability of lambda delegates. All the syntactic 
>>> sugar is nice, but it also lays a few traps for the unwary.  Here is 
>>> a simple example:
>>>
>>> // The Fibonacci numbers are an integer sequence such that
>>> //        F(n) = F(n - 1) + F(n - 2)
>>> //        And F(0) = 0, F(1) = 1
>>> int delegate() fibs()
>>> {
>>>     int a = 0;            // Initialize the last two terms of the 
>>> Fibonacci     int b = 1;
>>>
>>>     return
>>>     {
>>>         int c = a + b;     // Calculate the next term in the sequence
>>>         a = b;               // Shift the previous terms back
>>>         b = c;
>>>         return c;            // Return the result
>>>     };
>>> }
>>>
>>> This function returns a function which will sequentially evaluate all 
>>> of the Fibonacci numbers.  Notice that the inner delegate modifies 
>>> the variables a and b in fibs() scope.  Because of this, it is not 
>>> guaranteed to work after fibs returns.  This is most irritating, and 
>>> it greatly restricts the use of this technique. Another potential use 
>>> for lambda delegates is to create one-line adapter methods.  Consider 
>>> the following attempt to create a button which will display an 
>>> arbitrary message when clicked:
>>
>> It took me awhile to get what you were doing but it is elegant -- or 
>> would be if it worked. I am sure I am missing something however so I 
>> hope you might explain why using static storage is not sufficient:
>>
>> int delegate() fibs()
>> {
>>   return
>>   {
>>     static int a = 0;
>>     static int b = 1;
>>     int c = a + b;
>>     a = b;
>>     b = c ;
>>     return c;
>>   };
>> }
>>
> 
> For starters, a delegate can access the outer function arguments, but 
> those arguments cannot be made static.
> 
> And then there will only be one "instance" of the returned delegate 
> (think of the delegate as an object). Any call to it will update only 
> one single sequence:
> 
>   auto dg1 = fibs();
>   auto dg2 = fibs();
>   dg1(); // 1
>   dg1(); // 2
>   dg2(); // 3
>   dg2(); // 5
> 
> However, with proper "heaped" frames, there are many delegate (outer 
> frame) "instances":
> 
>   auto dg1 = fibs();
>   auto dg2 = fibs();
>   dg1(); // 1
>   dg1(); // 2
>   dg1(); // 3
>   dg2(); // 1
>   dg2(); // 2
>   dg2(); // 3
> 

Thanks for the reply. Your reply certainly helped me see the issues more 
clearly. I took some time and played with static storage just a bit more to see 
where its limits are. It is possible to get scoped vars into static fields. The 
real problem is somehow getting individual delegates to recognize which index is 
theirs. You should notice that in addition to making tables for multiple values 
there is also a table which stores all the delegates made. If there were a way 
to scan the table for the delegate within the delegate when everytime it is run 
then the problem would be solved.


   const int MAX_CONSECUTIVE_FIBS = 8;

   int delegate() fibs()
   {
     int a = 0;
     int b = 1;


     int delegate() fibs_dg_wrapper()
     {
       static int[MAX_CONSECUTIVE_FIBS] a_table;
       static int[MAX_CONSECUTIVE_FIBS] b_table;
       static int delegate()[MAX_CONSECUTIVE_FIBS] d_table;
       static int last_index = -1;

       last_index += 1;
       a_table[last_index] = a; // a valid in this wrapper func
       b_table[last_index] = b; // b valid in this wrapper func
       d_table[last_index] =    // keep reference to each dg
       {
         // would work if I could scan table for this dg
         // no idea how to do that and hence the printfs
         int my_index = last_index;

         int c = a_table[my_index] + b_table[my_index];
         a_table[my_index] = b_table[my_index];
         b_table[my_index] = c;
         dout.printf("fibs_dg @ %X\n",d_table[my_index]);
         dout.printf("fibs_dg.c @ %X\n\n",&c);
         return c;
       };
       return d_table[last_index];
     };
     return fibs_dg_wrapper();
   }



   int main(char[][] args)
     int delegate() fibsdg1 = fibs_multi();
     dout.printf("%d\n",fibsdg1());
     dout.printf("%d\n",fibsdg1());
     dout.printf("%d\n",fibsdg1());
     dout.printf("%d\n",fibsdg1());
     dout.printf("%d\n",fibsdg1());
     dout.printf("\n");
     int delegate() fibsdg2 = fibs_multi();
     dout.printf("%d\n",fibsdg2());
     dout.printf("%d\n",fibsdg2());
     dout.printf("%d\n",fibsdg2());
     dout.printf("%d\n",fibsdg2());
     dout.printf("%d\n",fibsdg2());
     dout.printf("\n");

   }



More information about the Digitalmars-d mailing list