Thread overview
foreach limitations?
Aug 12, 2004
Russ Lewis
Aug 12, 2004
Jan Bendtsen
Aug 12, 2004
Russ Lewis
Aug 12, 2004
Ilya Minkov
Aug 13, 2004
Matthew
Aug 12, 2004
Mikola Lysenko
Aug 12, 2004
Russ Lewis
August 12, 2004
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?

August 12, 2004
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) { ... }
[snip]

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
August 12, 2004
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).

August 12, 2004
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)




August 12, 2004
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) { ... }
  }

August 12, 2004
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
August 13, 2004
One should be able to foreach over all the elements in a static array, or any slice thereof.