Thread overview
Const foreach
Nov 22, 2010
bearophile
Nov 22, 2010
Simen kjaeraas
Nov 22, 2010
Jonathan M Davis
Nov 22, 2010
bearophile
Nov 22, 2010
Jonathan M Davis
Nov 22, 2010
spir
Nov 22, 2010
Simen kjaeraas
Nov 22, 2010
Pelle Månsson
Nov 22, 2010
Simen kjaeraas
November 22, 2010
If in a D2 program I have an array of mutable items I may want to iterate on them but not modify them, so I'd like the iteration variable to be const. This is possible, but it seems I lose type inference:


void main() {
    int[3] array; // not const
    // foreach (const x; array) {}                // Error
    // foreach (const auto x; array) {}           // Error
    // foreach (const(int) x; array) {}           // OK
    foreach (const(typeof(array[0])) x; array) {} // OK
}


Is something wrong in that code? Is this a known limitation, an inevitable one? Is this an enhancement request worth adding to Bugzilla?

Bye and thank you,
bearophile
November 22, 2010
bearophile <bearophileHUGS@lycos.com> wrote:

> If in a D2 program I have an array of mutable items I may want to iterate on them but not modify them, so I'd like the iteration variable to be const. This is possible, but it seems I lose type inference:
>
>
> void main() {
>     int[3] array; // not const
>     // foreach (const x; array) {}                // Error
>     // foreach (const auto x; array) {}           // Error
>     // foreach (const(int) x; array) {}           // OK
>     foreach (const(typeof(array[0])) x; array) {} // OK
> }
>
>
> Is something wrong in that code? Is this a known limitation, an inevitable one? Is this an enhancement request worth adding to Bugzilla?

Definitely worth adding to bugzilla. I can't find the post now, but there
is a good description of how foreach loops can be rewritten as for loops,
with type inference. Further testing shows that 'auto' creates the same
problems, so it seems foreach is simply magical.

-- 
Simen
November 22, 2010
On Sunday 21 November 2010 17:21:14 bearophile wrote:
> If in a D2 program I have an array of mutable items I may want to iterate on them but not modify them, so I'd like the iteration variable to be const. This is possible, but it seems I lose type inference:
> 
> 
> void main() {
>     int[3] array; // not const
>     // foreach (const x; array) {}                // Error
>     // foreach (const auto x; array) {}           // Error
>     // foreach (const(int) x; array) {}           // OK
>     foreach (const(typeof(array[0])) x; array) {} // OK
> }
> 
> 
> Is something wrong in that code? Is this a known limitation, an inevitable one? Is this an enhancement request worth adding to Bugzilla?

Actually, const is pointless in your example, since you're dealing with a value type. Where it would matter is if you were dealing with an element type which was a reference type or if you marked x as a ref. And unfortunately, I don't think that it works to use const ref in a foreach (I've never gotten it work anyway) - probably for the same reason that const ref won't take an lvalue (and I _really_ wish that it would). _That_ would likely be worth opening up an enhancement request for, and it's probably necessary to get foreach to work properly with const.

- Jonathan M Davis
November 22, 2010
Jonathan M Davis:

> Actually, const is pointless in your example, since you're dealing with a value type.

A const value time is meaningful, it means that you are saying the D compiler that you don't want to modify it. Generally it's good to stick a const/immutable even when you use values inside your functions.


> And unfortunately, I don't think that it works to use const ref in a foreach (I've never gotten it work anyway)

I think it works (it has the same problems of the const alone, there is no type inference):

void main() {
    int[3] array;
    foreach (ref const(int) x; array) {}
}

Bye,
bearophile
November 22, 2010
On Sunday 21 November 2010 18:37:01 bearophile wrote:
> Jonathan M Davis:
> > Actually, const is pointless in your example, since you're dealing with a value type.
> 
> A const value time is meaningful, it means that you are saying the D compiler that you don't want to modify it. Generally it's good to stick a const/immutable even when you use values inside your functions.

True. But it's really only to help the compiler optimize better and perhaps to stop yourself from accidentally mutating it if you don't want it to happen. If the compiler's good enough, it shouldn't matter at all.

> > And unfortunately, I don't
> > think that it works to use const ref in a foreach (I've never gotten it
> > work anyway)
> 
> I think it works (it has the same problems of the const alone, there is no
> type inference):
> 
> void main() {
>     int[3] array;
>     foreach (ref const(int) x; array) {}
> }

It never occurred to me to use ref const(T). I tried const ref T, and that didn't worked (or maybe I only tried const ref - I don't recall). In any case, I've never figured out how to get const ref to work for foreach, so if what you give there works, that's great.

- Jonathan M Davis
November 22, 2010
On Sun, 21 Nov 2010 20:21:14 -0500
bearophile <bearophileHUGS@lycos.com> wrote:

> If in a D2 program I have an array of mutable items I may want to iterate on them but not modify them, so I'd like the iteration variable to be const. This is possible, but it seems I lose type inference:
> 
> 
> void main() {
>     int[3] array; // not const
>     // foreach (const x; array) {}                // Error
>     // foreach (const auto x; array) {}           // Error
>     // foreach (const(int) x; array) {}           // OK
>     foreach (const(typeof(array[0])) x; array) {} // OK
> }
> 
> 
> Is something wrong in that code? Is this a known limitation, an inevitable one? Is this an enhancement request worth adding to Bugzilla?
> 
> Bye and thank you,
> bearophile

Maybe you'll find it weird, but I would expect
    foreach (const(auto) x; array) {};
to be the logical idiom for this. "auto" beeing a kind of placeholder for a type name.
Presently yields the error:
    __trials__.d(25): basic type expected, not auto

denis
-- -- -- -- -- -- --
vit esse estrany ☣

spir.wikidot.com

November 22, 2010
spir <denis.spir@gmail.com> wrote:

> On Sun, 21 Nov 2010 20:21:14 -0500
> bearophile <bearophileHUGS@lycos.com> wrote:
>
>> If in a D2 program I have an array of mutable items I may want to iterate on them but not modify them, so I'd like the iteration variable to be const. This is possible, but it seems I lose type inference:
>>
>>
>> void main() {
>>     int[3] array; // not const
>>     // foreach (const x; array) {}                // Error
>>     // foreach (const auto x; array) {}           // Error
>>     // foreach (const(int) x; array) {}           // OK
>>     foreach (const(typeof(array[0])) x; array) {} // OK
>> }
>>
>>
>> Is something wrong in that code? Is this a known limitation, an inevitable one? Is this an enhancement request worth adding to Bugzilla?
>>
>> Bye and thank you,
>> bearophile
>
> Maybe you'll find it weird, but I would expect
>     foreach (const(auto) x; array) {};
> to be the logical idiom for this. "auto" beeing a kind of placeholder for a type name.

'auto' is not a placeholder for a type, but the default storage class.
IOW, 'int n;' == 'auto int n;'. This does however not compile,
complaining that it has no effect.

Specifying just the storage class signals the compiler to use type
inference. Try it:

const x = 4;
immutable y = 4;

-- 
Simen
November 22, 2010
On 11/22/2010 04:12 PM, Simen kjaeraas wrote:
> spir <denis.spir@gmail.com> wrote:
>
>> On Sun, 21 Nov 2010 20:21:14 -0500
>> bearophile <bearophileHUGS@lycos.com> wrote:
>>
>>> If in a D2 program I have an array of mutable items I may want to
>>> iterate on them but not modify them, so I'd like the iteration
>>> variable to be const. This is possible, but it seems I lose type
>>> inference:
>>>
>>>
>>> void main() {
>>> int[3] array; // not const
>>> // foreach (const x; array) {} // Error
>>> // foreach (const auto x; array) {} // Error
>>> // foreach (const(int) x; array) {} // OK
>>> foreach (const(typeof(array[0])) x; array) {} // OK
>>> }
>>>
>>>
>>> Is something wrong in that code? Is this a known limitation, an
>>> inevitable one? Is this an enhancement request worth adding to Bugzilla?
>>>
>>> Bye and thank you,
>>> bearophile
>>
>> Maybe you'll find it weird, but I would expect
>> foreach (const(auto) x; array) {};
>> to be the logical idiom for this. "auto" beeing a kind of placeholder
>> for a type name.
>
> 'auto' is not a placeholder for a type, but the default storage class.
> IOW, 'int n;' == 'auto int n;'. This does however not compile,
> complaining that it has no effect.
>
> Specifying just the storage class signals the compiler to use type
> inference. Try it:
>
> const x = 4;
> immutable y = 4;
>

I'm not sure you are correct:

    const static auto x = 4;
November 22, 2010
Pelle Månsson <pelle.mansson@gmail.com> wrote:

>> 'auto' is not a placeholder for a type, but the default storage class.
>> IOW, 'int n;' == 'auto int n;'. This does however not compile,
>> complaining that it has no effect.
>>
>> Specifying just the storage class signals the compiler to use type
>> inference. Try it:
>>
>> const x = 4;
>> immutable y = 4;
>>
>
> I'm not sure you are correct:
>
>      const static auto x = 4;

I don't see how this contradicts anything I've said. You can safely
remove auto from that statement, and the type will be inferred to the
same. The fact that it compiles is a compiler bug, if we take the
error message in the 'auto int x;' example to be representative.

-- 
Simen