www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Foreach problem

reply "Tim M" <a b.com> writes:
Why is this an error. Dmd wants to make sure that I declare a new variable  
in the foreach statement and not use an existing one?

module test;

void main()
{
	int i;
	int[] nums;
	foreach(i; nums)
	{
		//
	}
}


dmd test.d

test.d(7): Error: shadowing declaration test.main.i is deprecated
Jan 10 2009
next sibling parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Tim M wrote:
 
 Why is this an error. Dmd wants to make sure that I declare a new 
 variable in the foreach statement and not use an existing one?
 
 module test;
 
 void main()
 {
     int i;
     int[] nums;
     foreach(i; nums)
     {
         //
     }
 }
 
 
 dmd test.d
 
 test.d(7): Error: shadowing declaration test.main.i is deprecated
Yes; as the error states, you're not allowed to define variables with the same name as variables in an enclosing scope any more. -- Daniel
Jan 10 2009
parent reply "Tim M" <a b.com> writes:
On Sun, 11 Jan 2009 15:50:54 +1300, Daniel Keep  
<daniel.keep.lists gmail.com> wrote:

 Tim M wrote:
  Why is this an error. Dmd wants to make sure that I declare a new  
 variable in the foreach statement and not use an existing one?
  module test;
  void main()
 {
     int i;
     int[] nums;
     foreach(i; nums)
     {
         //
     }
 }
   dmd test.d
  test.d(7): Error: shadowing declaration test.main.i is deprecated
Yes; as the error states, you're not allowed to define variables with the same name as variables in an enclosing scope any more. -- Daniel
Why does it still work for some objects?
Jan 10 2009
parent reply "Tim M" <a b.com> writes:
On Sun, 11 Jan 2009 15:59:26 +1300, Tim M <a b.com> wrote:

 On Sun, 11 Jan 2009 15:50:54 +1300, Daniel Keep  
 <daniel.keep.lists gmail.com> wrote:

 Tim M wrote:
  Why is this an error. Dmd wants to make sure that I declare a new  
 variable in the foreach statement and not use an existing one?
  module test;
  void main()
 {
     int i;
     int[] nums;
     foreach(i; nums)
     {
         //
     }
 }
   dmd test.d
  test.d(7): Error: shadowing declaration test.main.i is deprecated
Yes; as the error states, you're not allowed to define variables with the same name as variables in an enclosing scope any more. -- Daniel
Why does it still work for some objects?
This works: module test; class A { this() { // } } class B { this() { // } int opApply (int delegate (inout B) dg) { return 1; } } void main() { A a; B b; foreach(a; b) { // } }
Jan 10 2009
next sibling parent reply Bill Baxter <wbaxter gmail.com> writes:
On Sun, Jan 11, 2009 at 12:04 PM, Tim M <a b.com> wrote:
 On Sun, 11 Jan 2009 15:59:26 +1300, Tim M <a b.com> wrote:
 Why does it still work for some objects?
This works: module test; class A { this() { // } } class B { this() { // } int opApply (int delegate (inout B) dg) { return 1; } } void main() { A a; B b; foreach(a; b) { // } }
Interesting. But there the inner 'a' is actually a B. So it compiles, but there's no way it's using the outer 'a' as the counter variable. --bb
Jan 10 2009
parent reply "Tim M" <a b.com> writes:
On Sun, 11 Jan 2009 16:10:39 +1300, Bill Baxter <wbaxter gmail.com> wrote:

 On Sun, Jan 11, 2009 at 12:04 PM, Tim M <a b.com> wrote:
 On Sun, 11 Jan 2009 15:59:26 +1300, Tim M <a b.com> wrote:
 Why does it still work for some objects?
This works: module test; class A { this() { // } } class B { this() { // } int opApply (int delegate (inout B) dg) { return 1; } } void main() { A a; B b; foreach(a; b) { // } }
Interesting. But there the inner 'a' is actually a B. So it compiles, but there's no way it's using the outer 'a' as the counter variable. --bb
Sorry for my typo but change that line to: int opApply (int delegate (inout A) dg) and it still compiles.
Jan 10 2009
parent Bill Baxter <wbaxter gmail.com> writes:
On Sun, Jan 11, 2009 at 12:15 PM, Tim M <a b.com> wrote:
 On Sun, 11 Jan 2009 16:10:39 +1300, Bill Baxter <wbaxter gmail.com> wrote:

 On Sun, Jan 11, 2009 at 12:04 PM, Tim M <a b.com> wrote:
 On Sun, 11 Jan 2009 15:59:26 +1300, Tim M <a b.com> wrote:
 Why does it still work for some objects?
This works: module test; class A { this() { // } } class B { this() { // } int opApply (int delegate (inout B) dg) { return 1; } } void main() { A a; B b; foreach(a; b) { // } }
Interesting. But there the inner 'a' is actually a B. So it compiles, but there's no way it's using the outer 'a' as the counter variable. --bb
Sorry for my typo but change that line to: int opApply (int delegate (inout A) dg) and it still compiles.
'Still compiles" or "then it will compile"? Anyway, I'm curious if it's using the outer A or not. Can you add a line or two to actually modify 'a' in the loop? --bb
Jan 10 2009
prev sibling parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Sun, 11 Jan 2009 06:04:01 +0300, Tim M <a b.com> wrote:

 On Sun, 11 Jan 2009 15:59:26 +1300, Tim M <a b.com> wrote:

 On Sun, 11 Jan 2009 15:50:54 +1300, Daniel Keep  
 <daniel.keep.lists gmail.com> wrote:

 Tim M wrote:
  Why is this an error. Dmd wants to make sure that I declare a new  
 variable in the foreach statement and not use an existing one?
  module test;
  void main()
 {
     int i;
     int[] nums;
     foreach(i; nums)
     {
         //
     }
 }
   dmd test.d
  test.d(7): Error: shadowing declaration test.main.i is deprecated
Yes; as the error states, you're not allowed to define variables with the same name as variables in an enclosing scope any more. -- Daniel
Why does it still work for some objects?
This works: module test; class A { this() { // } } class B { this() { // } int opApply (int delegate (inout B) dg) { return 1; } } void main() { A a; B b; foreach(a; b) { // } }
It is a bug and should be reported.
Jan 10 2009
next sibling parent reply "Tim M" <a b.com> writes:
On Sun, 11 Jan 2009 19:56:55 +1300, Denis Koroskin <2korden gmail.com>  
wrote:

 On Sun, 11 Jan 2009 06:04:01 +0300, Tim M <a b.com> wrote:

 On Sun, 11 Jan 2009 15:59:26 +1300, Tim M <a b.com> wrote:

 On Sun, 11 Jan 2009 15:50:54 +1300, Daniel Keep  
 <daniel.keep.lists gmail.com> wrote:

 Tim M wrote:
  Why is this an error. Dmd wants to make sure that I declare a new  
 variable in the foreach statement and not use an existing one?
  module test;
  void main()
 {
     int i;
     int[] nums;
     foreach(i; nums)
     {
         //
     }
 }
   dmd test.d
  test.d(7): Error: shadowing declaration test.main.i is deprecated
Yes; as the error states, you're not allowed to define variables with the same name as variables in an enclosing scope any more. -- Daniel
Why does it still work for some objects?
This works: module test; class A { this() { // } } class B { this() { // } int opApply (int delegate (inout B) dg) { return 1; } } void main() { A a; B b; foreach(a; b) { // } }
It is a bug and should be reported.
Yep that probibly is a slight bug. What I would like to know is why cant I do foreach with primitive types like I can with objects. The objects use an existing variable but an int would require a new int defined with the foreach params.
Jan 10 2009
parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Sun, 11 Jan 2009 10:08:47 +0300, Tim M <a b.com> wrote:

 On Sun, 11 Jan 2009 19:56:55 +1300, Denis Koroskin <2korden gmail.com>  
 wrote:

 On Sun, 11 Jan 2009 06:04:01 +0300, Tim M <a b.com> wrote:

 On Sun, 11 Jan 2009 15:59:26 +1300, Tim M <a b.com> wrote:

 On Sun, 11 Jan 2009 15:50:54 +1300, Daniel Keep  
 <daniel.keep.lists gmail.com> wrote:

 Tim M wrote:
  Why is this an error. Dmd wants to make sure that I declare a new  
 variable in the foreach statement and not use an existing one?
  module test;
  void main()
 {
     int i;
     int[] nums;
     foreach(i; nums)
     {
         //
     }
 }
   dmd test.d
  test.d(7): Error: shadowing declaration test.main.i is deprecated
Yes; as the error states, you're not allowed to define variables with the same name as variables in an enclosing scope any more. -- Daniel
Why does it still work for some objects?
This works: module test; class A { this() { // } } class B { this() { // } int opApply (int delegate (inout B) dg) { return 1; } } void main() { A a; B b; foreach(a; b) { // } }
It is a bug and should be reported.
Yep that probibly is a slight bug. What I would like to know is why cant I do foreach with primitive types like I can with objects.
You can use foreach to iterate over arrays and tuples, if that's what you mean. Iterating over over primitive types makes little sense.
 The objects  
 use an existing variable but an int would require a new int defined with  
 the foreach params.
You got it wrong, foreach never use an existing variable. Try yourself: void main() { B b; foreach (a; b) { } } Variable shadowing is disallowed for this very reason - to avoid "what variable do I use here" type of confusion. The code you provided is incorrect, but compiler currently accepts it (which is a bug). You should remove "A a;" from the main, it is never used anyway.
Jan 10 2009
parent reply "Tim M" <a b.com> writes:
On Sun, 11 Jan 2009 20:31:51 +1300, Denis Koroskin <2korden gmail.com>  
wrote:


 Yep that probibly is a slight bug. What I would like to know is why  
 cant I do foreach with primitive types like I can with objects.
You can use foreach to iterate over arrays and tuples, if that's what you mean. Iterating over over primitive types makes little sense.
Just re reading my own question I think it is clear what I meant. I meant array of primitives so yes iterating over an array, but an array of primitives. Dmd handles foreach over SomeObject[] a lot more relaxed than int[].
Jan 11 2009
parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Sun, 11 Jan 2009 11:04:38 +0300, Tim M <a b.com> wrote:

 On Sun, 11 Jan 2009 20:31:51 +1300, Denis Koroskin <2korden gmail.com>  
 wrote:


 Yep that probibly is a slight bug. What I would like to know is why  
 cant I do foreach with primitive types like I can with objects.
You can use foreach to iterate over arrays and tuples, if that's what you mean. Iterating over over primitive types makes little sense.
Just re reading my own question I think it is clear what I meant. I meant array of primitives so yes iterating over an array, but an array of primitives. Dmd handles foreach over SomeObject[] a lot more relaxed than int[].
Example, please? I never noticed any difference.
Jan 11 2009
parent "Tim M" <a b.com> writes:
On Sun, 11 Jan 2009 21:39:55 +1300, Denis Koroskin <2korden gmail.com>  
wrote:

 On Sun, 11 Jan 2009 11:04:38 +0300, Tim M <a b.com> wrote:

 On Sun, 11 Jan 2009 20:31:51 +1300, Denis Koroskin <2korden gmail.com>  
 wrote:


 Yep that probibly is a slight bug. What I would like to know is why  
 cant I do foreach with primitive types like I can with objects.
You can use foreach to iterate over arrays and tuples, if that's what you mean. Iterating over over primitive types makes little sense.
Just re reading my own question I think it is clear what I meant. I meant array of primitives so yes iterating over an array, but an array of primitives. Dmd handles foreach over SomeObject[] a lot more relaxed than int[].
Example, please? I never noticed any difference.
Ok just did another test. Objects are handled the same way like you said. The "problem" is actually in the opApply where it can work just fine (runs ok not just compiles ok) using the exisiting variable.
Jan 11 2009
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Denis Koroskin" wrote
 On Sun, 11 Jan 2009 06:04:01 +0300, Tim M <a b.com> wrote:

 On Sun, 11 Jan 2009 15:59:26 +1300, Tim M <a b.com> wrote:

 On Sun, 11 Jan 2009 15:50:54 +1300, Daniel Keep 
 <daniel.keep.lists gmail.com> wrote:

 Tim M wrote:
  Why is this an error. Dmd wants to make sure that I declare a new 
 variable in the foreach statement and not use an existing one?
  module test;
  void main()
 {
     int i;
     int[] nums;
     foreach(i; nums)
     {
         //
     }
 }
   dmd test.d
  test.d(7): Error: shadowing declaration test.main.i is deprecated
Yes; as the error states, you're not allowed to define variables with the same name as variables in an enclosing scope any more. -- Daniel
Why does it still work for some objects?
This works: module test; class A { this() { // } } class B { this() { // } int opApply (int delegate (inout B) dg) { return 1; } } void main() { A a; B b; foreach(a; b) { // } }
It is a bug and should be reported.
I'm not so sure. Would you say this is a bug (it compiles)? int foo() { int i; int innerfoo(int i) { return i; } return innerfoo(2); // returns 2 } because that's basically what a foreach does when using opApply: create an inner function and then pass a delegate pointing to that function to opApply. I think the difference between the two is that the compiler handles foreach on an array in a special manner without using an inner function/delegate. This also fails to compile: void main() { A a; A[] b; foreach(a; b) { // } }
Jan 12 2009
parent Bill Baxter <wbaxter gmail.com> writes:
On Tue, Jan 13, 2009 at 6:25 AM, Steven Schveighoffer
<schveiguy yahoo.com> wrote:

 because that's basically what a foreach does when using opApply: create an
 inner function and then pass a delegate pointing to that function to
 opApply.

 I think the difference between the two is that the compiler handles foreach
 on an array in a special manner without using an inner function/delegate.
That's an implementation detail and shouldn't effect the behavior visible to the user. --bb
Jan 12 2009
prev sibling next sibling parent "Jarrett Billingsley" <jarrett.billingsley gmail.com> writes:
On Sat, Jan 10, 2009 at 9:33 PM, Tim M <a b.com> wrote:
 Why is this an error. Dmd wants to make sure that I declare a new variable
 in the foreach statement and not use an existing one?
You can't reuse existing variables as foreach loop indices, long story short.
Jan 10 2009
prev sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Sun, Jan 11, 2009 at 11:33 AM, Tim M <a b.com> wrote:
 Why is this an error. Dmd wants to make sure that I declare a new variable
 in the foreach statement and not use an existing one?

 module test;

 void main()
 {
        int i;
        int[] nums;
        foreach(i; nums)
        {
                //
        }
 }


 dmd test.d

 test.d(7): Error: shadowing declaration test.main.i is deprecated
I think this should be allowable. It's basically an unfortunate side effect of the decision to make the loop variables in foreach implicitly 'auto'. I'd kinda forgotten about that, but I remember when I first saw it thinking it looked like a particularly odious bit of special casing just in the name of saving a few keystrokes. It's the only place in D where you can declare a variable without any type or storage class AFAIK. The only think like it is some of the crazy 'is( )' expressions where you can define a new type without any 'alias' or 'typedef'. I wouldn't cry if D2 made specifying 'auto' a requirement in foreach. And allowed using an outer variable as the index like every other loop. It would certainly be more consistent. --bb
Jan 10 2009