www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - foreach limitations?

reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
I ran into some unexpected complexities with foreach-ing over a 
multidimensional static array.  I tried this code, which didn't work:

   int[10][100] foo;
   foreach(inout int i; foo) { ... }

I guess I can understand that you can't foreach over a multidimensional 
array.  But it would be cool for 2.0.  So I tried this next, which 
didn't work, either:

   int[10][100] foo;
   foreach(inout int[] a; foo) foreach(inout int i; a) { ... }

It seems that if you foreach over something, and the elements are static 
arrays, you can't have a dynamic array as the foreach variable.  So I 
was left with this ugly code:

   int[10][100] foo;
   foreach(inout int[10] a; foo) foreach(inout int i; a) { ... }

So I'm wondering why we can't do my second example above.  Is there some 
intentional reason why?  Or just an oversight in the compiler?
Aug 12 2004
next sibling parent reply Jan Bendtsen <dimon controlREMOVEME.aau.dk> writes:
Hi,

Russ Lewis wrote:

 I ran into some unexpected complexities with foreach-ing over a 
 multidimensional static array.  I tried this code, which didn't work:
 
   int[10][100] foo;
   foreach(inout int i; foo) { ... }
 
 I guess I can understand that you can't foreach over a multidimensional 
 array.  But it would be cool for 2.0.  So I tried this next, which 
 didn't work, either:
 
   int[10][100] foo;
   foreach(inout int[] a; foo) foreach(inout int i; a) { ... }

On a tangentially related note, what is more efficient in terms of execution speed, the code above or int[10][100] foo; for(int i = 0; i < foo.length; i++) { for(int j = 0; j < foo[i].length; j++) { // Do some stuff, e.g., foo[i][j] = cosh(i*j); } } ? (ignoring any implications inout might have, if that makes a difference) I'm asking out of curiosity... what is the 'best' practice in a case like this? Cheers, Jan
Aug 12 2004
next sibling parent Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Jan Bendtsen wrote:
 On a tangentially related note, what is more efficient in terms of 
 execution speed, the code above or
 
     int[10][100] foo;
     for(int i = 0; i < foo.length; i++) {
         for(int j = 0; j < foo[i].length; j++) {
             // Do some stuff, e.g., foo[i][j] = cosh(i*j);
         }
     }
 ?
 (ignoring any implications inout might have, if that makes a difference)
 
 I'm asking out of curiosity... what is the 'best' practice in a case 
 like this?

They are both O(i*j) algorithms, so I would generally say that either one is as good as the other. The two loops are really the same thing, so the real difference is going to be how good the compiler is at optimizing the loop. You don't really know how good your compiler will be until you look at the assembly language. So I would recommend that you use whatever loop you think is more readable and maintainable (I prefer foreach, though you may think differently).
Aug 12 2004
prev sibling parent reply Ilya Minkov <minkov cs.tum.edu> writes:
Jan Bendtsen schrieb:

 I ran into some unexpected complexities with foreach-ing over a 
 multidimensional static array.  I tried this code, which didn't work:

   int[10][100] foo;
   foreach(inout int i; foo) { ... }

 I guess I can understand that you can't foreach over a 
 multidimensional array.  But it would be cool for 2.0.  


I think what we need are real multidimensional arrays in 2.0 - what we have now is arrayarrays. I have suggested them multiple times, and Norbert Nemec has formulated a detailed proposal in "Proposal for multidimensional arrays". They would solve this problem neatly as well. I think also that a template library would close the for-each-element gap.
 So I tried 
 this next, which didn't work, either:

   int[10][100] foo;
   foreach(inout int[] a; foo) foreach(inout int i; a) { ... }


This looks like a bug. int[10] ought to be assignable to int[], though apparently not all parts of the compiler are aware of that. :) Although this might be a spot where it's better not to convert due to performance reasons.
 On a tangentially related note, what is more efficient in terms of 
 execution speed, the code above or
 
     int[10][100] foo;
     for(int i = 0; i < foo.length; i++) {
         for(int j = 0; j < foo[i].length; j++) {
             // Do some stuff, e.g., foo[i][j] = cosh(i*j);
         }
     }
 ?
 (ignoring any implications inout might have, if that makes a difference)
 
 I'm asking out of curiosity... what is the 'best' practice in a case 
 like this?

I think it doesn't make any difference right now, but foreach offers much more optimization potential in the primitive cases. Besides, it's the only sane way to iterate through other containers, such as associative arrays and user-defined types, so i'd say foreach is preferred. -eye
Aug 12 2004
parent "Matthew" <admin.hat stlsoft.dot.org> writes:
One should be able to foreach over all the elements in a static array, or any
slice thereof.
Aug 12 2004
prev sibling parent reply Mikola Lysenko <Mikola_member pathlink.com> writes:
In article <cfgd71$2flp$1 digitaldaemon.com>, Russ Lewis says...
It seems that if you foreach over something, and the elements are static 
arrays, you can't have a dynamic array as the foreach variable.  So I 
was left with this ugly code:

   int[10][100] foo;
   foreach(inout int[10] a; foo) foreach(inout int i; a) { ... }

So I'm wondering why we can't do my second example above.  Is there some 
intentional reason why?  Or just an oversight in the compiler?

The reason is that dynamic arrays have two attributes 1). Length of the array 2). A pointer to the start of the array Static arrays on the other hand directly reference a chunk of memory allocated for the array elements. The compiler treats both types differently. Your original code would work if you declared foo as such # int[][] foo = new int[100][10]; A foreach over a static array and a foreach over a dynamic array are two slightly different things. The static-foreach looks up the name in the symbol table and finds the length of the array once at compile time, while the dynamic-foreach simply uses the length attribute. You can see evidence of this in the .sizeof method for the two different array types. # int[5] a; # int[] b = new int[5]; In this example, a.sizeof = 20 while b.sizeof = 8 (32 bits for start of array, 32 bits for length)
Aug 12 2004
parent Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Mikola Lysenko wrote:
 In article <cfgd71$2flp$1 digitaldaemon.com>, Russ Lewis says...
 
It seems that if you foreach over something, and the elements are static 
arrays, you can't have a dynamic array as the foreach variable.  So I 
was left with this ugly code:

  int[10][100] foo;
  foreach(inout int[10] a; foo) foreach(inout int i; a) { ... }

So I'm wondering why we can't do my second example above.  Is there some 
intentional reason why?  Or just an oversight in the compiler?

The reason is that dynamic arrays have two attributes 1). Length of the array 2). A pointer to the start of the array Static arrays on the other hand directly reference a chunk of memory allocated for the array elements. The compiler treats both types differently. Your original code would work if you declared foo as such # int[][] foo = new int[100][10]; A foreach over a static array and a foreach over a dynamic array are two slightly different things. The static-foreach looks up the name in the symbol table and finds the length of the array once at compile time, while the dynamic-foreach simply uses the length attribute.

Sure, I know this. But you can assign a static array to a dynamic array. But why can't the compiler turn this code: int[10][100] foo; foreach(inout int[] a; foo) foreach(inout int i; a) { ... } into this code: int[10][100] foo; foreach(inout int[10] _compiler_temp__a; foo) { int[] a = _compiler_temp__a; foreach(inout int i; a) { ... } }
Aug 12 2004