About foreach loops

Timon Gehr timon.gehr at gmx.ch
Wed Jun 15 12:20:45 PDT 2011


On 6/15/11 1:14 PM, 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.

key should not be const imho.

1. const pollution.
2. does not work satisfactory with pointers/user defined structs with indirections.

3? Does not work with structs with a postblit:
tt.d(16): Error: function tt.S.__cpctor (ref S p) is not callable using argument
types (S) const
Is that a compiler bug or a limitation of the language? Is there any way to define
a const postblit operator? If yes, see 1.



Timon



More information about the Digitalmars-d mailing list