www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Const foreach

reply bearophile <bearophileHUGS lycos.com> writes:
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
Nov 21 2010
next sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
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
Nov 21 2010
prev sibling next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
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
Nov 21 2010
parent bearophile <bearophileHUGS lycos.com> writes:
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
Nov 21 2010
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
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
Nov 21 2010
prev sibling next sibling parent reply spir <denis.spir gmail.com> writes:
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=

t. This is possible, but it seems I lose type inference:
=20
=20
 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
 }
=20
=20
 Is something wrong in that code? Is this a known limitation, an inevitabl=

=20
 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 =E2=98=A3 spir.wikidot.com
Nov 22 2010
parent =?UTF-8?B?UGVsbGUgTcOlbnNzb24=?= <pelle.mansson gmail.com> writes:
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;
Nov 22 2010
prev sibling next sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
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
Nov 22 2010
prev sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Pelle M=C3=A5nsson <pelle.mansson gmail.com> wrote:

 'auto' is not a placeholder for a type, but the default storage class=


 IOW, 'int n;' =3D=3D '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 =3D 4;
 immutable y =3D 4;

I'm not sure you are correct: const static auto x =3D 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
Nov 22 2010