About foreach loops

Don nospam at nospam.com
Wed Jun 15 13:14:36 PDT 2011


KennyTM~ wrote:
> On Jun 16, 11 00:53, Andrei Alexandrescu wrote:
>> On 6/15/11 11:51 AM, KennyTM~ wrote:
>>> On Jun 15, 11 23:23, Caligo wrote:
>>>> On Wed, Jun 15, 2011 at 9:44 AM, KennyTM~<kennytm at gmail.com> wrote:
>>>>> On Jun 15, 11 22:35, Caligo wrote:
>>>>>>
>>>>>> You can create a temporary if you like:
>>>>>>
>>>>>> foreach(i; 0..10){
>>>>>> int ii = i + 1;
>>>>>> writeln(ii, " ");
>>>>>> }
>>>>>>
>>>>>> Which outputs:
>>>>>> 1 2 3 4 5 6 7 8 9 10
>>>>>>
>>>>>>
>>>>>> The problem with trying to "fix" foreach is that it would create
>>>>>> problems of its own. The following code would not behave correctly:
>>>>>>
>>>>>> foreach(i; 0..10){
>>>>>> if(i& 1)
>>>>>> i += 1;
>>>>>> writeln(i, " is even.");
>>>>>> }
>>>>>>
>>>>>> not to mention all the code that's already using foreach.
>>>>>
>>>>> If the code rely on the 'implicit ref' behavior of 'i', the code is
>>>>> doing it
>>>>> wrong. The spec never mentioned what happened when the variable is
>>>>> modified
>>>>> in a ForeachRangeStatement. I believe it is more sane if modifying
>>>>> 'i' is
>>>>> disallowed unless 'ref' is used.
>>>>>
>>>>
>>>>
>>>> This should be a compile time error:
>>>>
>>>> foreach(i; 0..10){
>>>> i += 1;
>>>> write(i, " ");
>>>> }
>>>>
>>>> This should be legal.
>>>> foreach(ref i; 0..10){
>>>> i += 1;
>>>> write(i, " ");
>>>> }
>>>>
>>>> Is that the general consensus here?
>>>
>>> A simple patch for this:
>>>
>>> https://github.com/kennytm/dmd/compare/master...const_foreach_range
>>
>> Does that take care of change through an alias, e.g.
>>
>> int * p = i;
>> ++*p;
>>
>>
>> Andrei
> 
> 
> Error: cannot implicitly convert expression (i) of type const(int) to int*
> 
> 
> 
> What the patch does is simply rewrite
> 
>     foreach (key; lwr .. upr) body;
> 
> into
> 
>     foreach (auto __iterator1234 = lwr, auto __limit1235 = upr;
>              __iterator1234 < __limit1235;
>              __iterator1234++)
>     {
>        const key = __iterator1234;
>        body;
>     }
> 
> so as long as the 'const' system in D has no bug, the compiler can deny 
> all unintended mutation in the loop.
> 

The alternative would be to create __iterator1234 as const, and then 
cast away const in the ++ step. Ugly, but would eliminate the 
performance cost for structs.


More information about the Digitalmars-d mailing list