Thread overview | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
July 11, 2010 Multi dimensional array question. | ||||
---|---|---|---|---|
| ||||
Hello. I'm wondering why in D if you declare a fixed multi dimensional array, you have to reverse the index order to access an element. I know it has something to do with how tightly [] bind, but the consequence is that it seems so different to other languages, it makes it error prone. So here's some code that compiles and works: import std.stdio; int main() { int[3][5] marr; int i = 0; foreach( j, ref a; marr) { writefln( "%s: a.length = %s", j, a.length); foreach( ref v; a) { v = i++; } } /* This doesn't work. marr[0][>=3] is out of bounds!! writefln( "marr[0][0] = %s", marr[0][0]); writefln( "marr[0][1] = %s", marr[0][1]); writefln( "marr[0][2] = %s", marr[0][2]); writefln( "marr[0][3] = %s", marr[0][3]); writefln( "marr[0][4] = %s", marr[0][4]); writefln( "marr[1][0] = %s", marr[1][0]); writefln( "marr[1][1] = %s", marr[1][1]); writefln( "marr[1][2] = %s", marr[1][2]); writefln( "marr[1][3] = %s", marr[1][3]); writefln( "marr[1][4] = %s", marr[1][4]); */ writefln( "marr[0][0] = %s", marr[0][0]); writefln( "marr[1][0] = %s", marr[1][0]); writefln( "marr[2][0] = %s", marr[2][0]); writefln( "marr[3][0] = %s", marr[3][0]); writefln( "marr[4][0] = %s", marr[4][0]); writefln( ""); writefln( "marr[0][1] = %s", marr[0][1]); writefln( "marr[1][1] = %s", marr[1][1]); writefln( "marr[2][1] = %s", marr[2][1]); writefln( "marr[3][1] = %s", marr[3][1]); writefln( "marr[4][1] = %s", marr[4][1]); writefln( ""); writefln( "marr[0][2] = %s", marr[0][2]); writefln( "marr[1][2] = %s", marr[1][2]); writefln( "marr[2][2] = %s", marr[2][2]); writefln( "marr[3][2] = %s", marr[3][2]); writefln( "marr[4][2] = %s", marr[4][2]); writefln( ""); return 0; } Anyways, perhaps I am doing something wrong, or I have been writing too much C code. What are your thoughts? |
July 11, 2010 Re: Multi dimensional array question. | ||||
---|---|---|---|---|
| ||||
Posted in reply to dcoder | dcoder <gtdegamo@yahoo.com> wrote: > I'm wondering why in D if you declare a fixed multi dimensional array, you > have to reverse the index order to access an element. I know it has something > to do with how tightly [] bind, but the consequence is that it seems so > different to other languages, it makes it error prone. The idea is that T[] is an array of T, for any T. if T == int[3], T[] would be int[3][]. Also, for indexing, given T[] arr. arr[i] peels off the first layer, giving you a T. If arr[i] used the first set of brackets, generic functions would be thoroughly borked, as a T passed to a template as int[3] would lead to different indexing from a T of int. -- Simen |
July 11, 2010 Re: Multi dimensional array question. | ||||
---|---|---|---|---|
| ||||
Posted in reply to dcoder | Hello dcoder, > Hello. > > I'm wondering why in D if you declare a fixed multi dimensional array, > you have to reverse the index order to access an element. When declaring an array, the base type is getting wrapped. When using an array, the base types get unwrapped. Because both forms place the [] as a subfix and in both cases the sub-type/expression needs to be contiguous it end up the way it is. alias int[5] T T[7] aa; T a = aa[6]; int v = a[4]; or (int[5])[7] aa; int v = (aa[6])[4]; -- ... <IXOYE>< |
July 12, 2010 Re: Multi dimensional array question. | ||||
---|---|---|---|---|
| ||||
Posted in reply to dcoder | This had me crazy. I ended up putting the brackets on the variable, like int marr[3][5]; then it worked like marr[2][4] = 9; |
July 12, 2010 Re: Multi dimensional array question. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Heywood Floyd | Heywood Floyd: > This had me crazy. I ended up putting the brackets on the variable, like > int marr[3][5]; > then it worked like > marr[2][4] = 9; That's present only for compatibility with C syntax, this means that you can use it to perform a quicker port of C code to D, but you are supposed to later convert it to D-style array definitions. See also: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=113185 Bye, bearophile |
July 12, 2010 Re: Multi dimensional array question. | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | bearophile Wrote:
> Heywood Floyd:
> > This had me crazy. I ended up putting the brackets on the variable, like
> > int marr[3][5];
> > then it worked like
> > marr[2][4] = 9;
>
> That's present only for compatibility with C syntax, this means that you can use it to perform a quicker port of C code to D, but you are supposed to later convert it to D-style array definitions.
> See also:
> http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=113185
>
> Bye,
> bearophile
Aha, good to know! Thanks!
(So this might go away in the future? Or require a -cstyle compile flag?)
***
I have a feeling this "backwards"-array stuff is gonna be one of the things my brain will repel for as long as it can.
To me, it seems equal to saying "you declare a function like:
void foo(string name, int age){
//... }
And then call it by doing
foo(90,"Benny")
and this makes sense because the arguments are actually pushed on the stack in reverse at runtime, so they arrive in the correct order in the function. And this is especially important with tuples." or something.
Ok, I understand this has some deep purpose that I still don't understand, I'm just, yeah. *tear*
(Although this is way out of my league: For instance, if a T is an int[3][4], then why can't T[string] be a int[string][3][4], and be accessed with arr["a"][2][3]? Seems just like a matter of taste?)
/HF
PS. I was not the thread creator. I just used the creator's terminology to "stay on topic". Maybe too on topic : ) Not important really. Sorry for the confusion. DS.
|
July 12, 2010 Re: Multi dimensional array question. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Heywood Floyd | Heywood Floyd: > Aha, good to know! Thanks! > (So this might go away in the future? Or require a -cstyle compile flag?) It's just an idea of mine, my weight in D design is near zero, and Walter doesn't love warnings. I don't know if C-style array definitions will ever go away from D, don't hold your breath :-) But in D code I suggest to replace them with D-style array definitions when possible. > PS. I was not the thread creator. I just used the creator's terminology to "stay on topic". Maybe too on topic : ) Not important really. Sorry for the confusion. DS. I am sorry, my error :-( Bye, bearophile |
July 13, 2010 Re: Multi dimensional array question. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Heywood Floyd | On Mon, 12 Jul 2010 17:23:16 -0400, Heywood Floyd wrote: > bearophile Wrote: > >> Heywood Floyd: >> > This had me crazy. I ended up putting the brackets on the variable, >> > like >> > int marr[3][5]; >> > then it worked like >> > marr[2][4] = 9; >> >> That's present only for compatibility with C syntax, this means that you can use it to perform a quicker port of C code to D, but you are supposed to later convert it to D-style array definitions. See also: http://www.digitalmars.com/webnews/newsgroups.php? art_group=digitalmars.D&article_id=113185 >> >> Bye, >> bearophile > > Aha, good to know! Thanks! > (So this might go away in the future? Or require a -cstyle compile > flag?) > > *** > > I have a feeling this "backwards"-array stuff is gonna be one of the things my brain will repel for as long as it can. > > To me, it seems equal to saying "you declare a function like: > > > void foo(string name, int age){ > //... } > > > And then call it by doing > > foo(90,"Benny") > > and this makes sense because the arguments are actually pushed on the stack in reverse at runtime, so they arrive in the correct order in the function. And this is especially important with tuples." or something. > > Ok, I understand this has some deep purpose that I still don't understand, I'm just, yeah. *tear* (Although this is way out of my league: For instance, if a T is an int[3][4], then why can't T[string] be a int[string][3][4], and be accessed with arr["a"][2][3]? Seems just like a matter of taste?) But then arrays would be different from all other types! If you have an array of 3 Ts, that is written T[3], regardless of what T is. Now consider these two cases: A. T is an int. Then T[3] becomes int[3]. B. T is an int[string]. Then T[3] becomes int[string][3]. In case A, the first element of the array is accessed like this: int[3] a; int firstA = a[0]; Since a is an array of int, firstA is of course an int. But then, since b is an array of int[string], we have int[string][3] b; int[string] firstB = b[0]; If we again want to access element "foo" of the associative array which is firstB, we write firstB["foo"]. And so we have the following three ways to get to that element, which *must* be equivalent because that's how the language is defined: // Using firstB as an intermediate step int[string] firstB = b[0]; int x = firstB["foo"]; // Drop the intermediate variable firstB int x = (b[0])["foo"]; // Drop the redundant parentheses int x = b[0]["foo"]; So you see, it can't be any other way than the way it is. :) -Lars |
July 14, 2010 Re: Multi dimensional array question. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Lars T. Kyllingstad | Lars T. Kyllingstad Wrote:
>
> But then arrays would be different from all other types! If you have an array of 3 Ts, that is written T[3], regardless of what T is. Now consider these two cases:
>
> A. T is an int. Then T[3] becomes int[3].
>
> B. T is an int[string]. Then T[3] becomes int[string][3].
>
> In case A, the first element of the array is accessed like this:
>
> int[3] a;
> int firstA = a[0];
>
> Since a is an array of int, firstA is of course an int.
>
> But then, since b is an array of int[string], we have
>
> int[string][3] b;
> int[string] firstB = b[0];
>
> If we again want to access element "foo" of the associative array which is firstB, we write firstB["foo"]. And so we have the following three ways to get to that element, which *must* be equivalent because that's how the language is defined:
>
> // Using firstB as an intermediate step
> int[string] firstB = b[0];
> int x = firstB["foo"];
>
> // Drop the intermediate variable firstB
> int x = (b[0])["foo"];
>
> // Drop the redundant parentheses
> int x = b[0]["foo"];
>
> So you see, it can't be any other way than the way it is. :)
>
> -Lars
Thank you for the elaborate answer!
When you put it like that, it does make sense. But I'm sorry. I refuse. The reason I refuse is those examples are void of any higher semantic meaning. Once we add a semantic meaning, it simply becomes backwards:
int[MAX_WIDTH][MAX_HEIGHT] map2d;
map2d[x][y] = 9; // Wrong!
At least in my head, this is cognitive dissonance. To me, the language acts as if it's low-level semantics outweighs my high-level semantics and I should correct my thinking for that. I refuse! Seems to me it could just as well work as:
int[string][3] b;
int[3] firstB = b["foo"];
int i = firstB[0];
int j = (b["foo"])[0];
int k = b["foo"][0];
But I feel like I'm the only one feeling this, so I'll just let it go and hope my dear C-style arrays stay in :)
BR
/HF
PS. Never thought I'd find a reason to love C.. DS.
|
July 14, 2010 Re: Multi dimensional array question. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Heywood Floyd | On Wednesday, July 14, 2010 13:57:13 Heywood Floyd wrote:
>
> Thank you for the elaborate answer!
>
> When you put it like that, it does make sense. But I'm sorry. I refuse. The reason I refuse is those examples are void of any higher semantic meaning. Once we add a semantic meaning, it simply becomes backwards:
>
> int[MAX_WIDTH][MAX_HEIGHT] map2d;
> map2d[x][y] = 9; // Wrong!
>
> At least in my head, this is cognitive dissonance. To me, the language acts as if it's low-level semantics outweighs my high-level semantics and I should correct my thinking for that. I refuse! Seems to me it could just as well work as:
>
> int[string][3] b;
> int[3] firstB = b["foo"];
> int i = firstB[0];
> int j = (b["foo"])[0];
> int k = b["foo"][0];
>
> But I feel like I'm the only one feeling this, so I'll just let it go and hope my dear C-style arrays stay in :)
>
> BR
> /HF
>
> PS. Never thought I'd find a reason to love C.. DS.
Personally, I don't like it, but I also don't think that it necessarily makes sense to change it. From the point of view of how the compiler deduces types, it's exactly how it should work. The problem, of course, is that it doesn't match how we think. However, in order for us to be able to deduce complicated types, the compiler must be totally consistent in how it deduces the type. A prime example would be function pointers (particularly using the C syntax). To be able to pick it apart properly, you're going to have to understand how the compiler does it. The type is complicated enough that you're stuck. To read arrays in the reverse order that is done now, you'd have to read everything else in the reverse order to be consistent, which would really mean types like this:
[5](int) const a;
The whole thing is ugly. There's no question of that. But to "fix" it breaks other stuff. Types are read right to left. Being consistent with that makes it possible to understand more complicated types. The downside is that some simpler types become harder to understand. However, as long as you use dynamic arrays, this really isn't a problem.
int[][] a = new int[][](MAX_WIDTH, MAX_HEIGHT);
is totally clear and it works in the order that you think. The problem is when you use statically-allocated arrays. Personally, I'd advise you to just use dynamic arrays unless you do some profiling and find that a static array is better in a particular case. Doing things that way makes it so that the weird ordering in declarations isn't generally a problem.
I agree that this particular syntactic faux pas is a problem, but I don't think that anyone has come up with an appropriate solution. Simply reversing how it works now would make reading more complex types much harder. A more complex solution would likely be required. As it stands, it's a problem, but it's only a problem if you're declaring statically-allocated arrays. It's unpleasant, but it should be manageable.
- Jonathan M Davis
|
Copyright © 1999-2021 by the D Language Foundation