DMD 0.166 release

Ivan Senji ivan.senji_REMOVE_ at _THIS__gmail.com
Fri Sep 1 16:42:47 PDT 2006


Ivan Senji wrote:
> Chris Nicholson-Sauls wrote:
>>
>>
>> Ivan Senji wrote:
>>> Walter Bright wrote:
>>>
>>>> The implicit conversion to delegate just broke too much. Instead, 
>>>> I'm trying out Tom S.'s suggestion of using a 'lazy' parameter 
>>>> storage class.
>>>>
>>>> http://www.digitalmars.com/d/changelog.html
>>>
>>>
>>> Hmm, I am afraid I have to admit I'm a little bit puzzled by this 
>>> lazy thing.
>>>
>>> Let's say we have:
>>>
>>> void dotimes(int count, lazy void exp)
>>> {
>>>   for (int i = 0; i < count; i++)
>>>   {
>>>     exp();
>>>   }
>>> }
>>>
>>> and I can call it like this:
>>>
>>> int x;
>>> dotimes(5, x++);
>>>
>>> And it works as expected and x end up being 5.
>>>
>>> But shouldn't I also be allowed to pass in a delegate of the 
>>> appropriate type
>>>
>>> dotimes(5, {writefln(x); x++;});
>>>
>>> A funny thing happens: nothing. The loop in dotimes does get executed 
>>> 5 times but delegate passed in isn't called?
>>>
>>>
>>
>> This is because anonymous delegates are themselves expressions, and so 
>> your 'exp()' just evaluates to the delegate itself -- it does not 
>> invoke it.  However, to achieve what you were trying to do, just make 
>> use of parentheses and the comma operator.  Also, you may provide an 
>> overload that takes a lazy delegate.  Here is my own test program, 
>> which worked without issue:
> 
> Hmm, there is something about this lazy stuff that is troubling me and 
> I'm not exactly sure what it is and if I can explain it:
> 
> so it is x++ vs {writefln(x); x++;}
> 
> The first one is an expression that looks like it is executed at call 
> site but it isn't because that parameter is declared to be lazy. It is 
> executed inside dotimes. That is ok.
> 
> The second is a block of statements, actually it is a void delegate. It 
> isn't executed at call site so it also will not be executed in dotimes.
> To make it be executed in dotimes I have to make it into something that 
> looks like it is being executed: for example: {writefln(x); x++;}()
> 
> And this is when thing begin to suck (unless I am missing something?).
> 
> So if I had
> dotimes(5, x++);
> 
> and now if I want it to do 5 times somethin a bit more than just x++ i 
> cannot just write:
> dotimes(5, {writefln(); x++;});
> 
> And now a completly different function is called (one taking void 
> delegate() as argument), to get it to call the lazy function I have to 
> change to type from void delegate() to void by pretending to be calling 
> the delegate.
> 
> So is there a point to having lazy, I could only have written dotimes 
> that takes void delegate() an write this:
> 
> dotimes(5, {x++;});  and   dotimes(5, {writefln(); x++;} );
> 
> vs
> 
> dotimes(5, x++);     and   dotimes(5, {writefln(); x++;}() );
> 
> And now (while writing) I finally figure out what was troubling me: each 
> of these approaches has a pretty case and an ugly case, the two pretty 
> cases being:
> 
> dotimes(5, x++);  and   dotimes(5, {writefln(); x++;} );

Actually I just figured out i can have both pretty cases :) Hooray, just 
need to change dotimes to:

void dotimes(int count, void delegate()[] exp...)
{
   for (int i = 0; i < count; i++)
   {
     foreach(dg; exp)
       dg();
   }
}

With the added benefit of being able to do the craziest things:

dotimes(5, f++, writefln(f), f*=2);

being equal to:

dotimes(5, {f++; writefln(f); f*=2;});

This isn't bad afterall, but I've lost lazy on the way. (Note to self: 
figure out where to use lazy)



More information about the Digitalmars-d-announce mailing list