Re: Trying to understand multidimensional arrays in D

2020-12-22 Thread Ali Çehreli via Digitalmars-d-learn
On 12/22/20 10:53 AM, Rekel wrote:> On Tuesday, 22 December 2020 at 
16:56:18 UTC, Ali Çehreli wrote:

>> >[4]Foo b; /* an array of four Foos */
>>
>> [4] already has a meaning. ;)
>
> It  does in that context? Do tell, I'm unaware.

An array literal with a single int element 4:

  pragma(msg, typeof([4]));

prints int[].

> Also, is it possible to move entire thread to a different forum group? 😂
> This feels more like a discussion fit for 'general'.

I've seen others "cross reference" to other threads perhaps by CC'ing 
the other newsgroup as well. (In case it's not obvious, these are 
newsgroups with a "forum" interface.)


Ali




Re: Trying to understand multidimensional arrays in D

2020-12-22 Thread Rekel via Digitalmars-d-learn

On Tuesday, 22 December 2020 at 16:55:40 UTC, Mike Parker wrote:

On Tuesday, 22 December 2020 at 15:31:06 UTC, Rekel wrote:



Don't take that as a defence of changing pointer syntax by the 
way, just noting I think the argument pointers and arrays 
should be defined using a similar syntax is not consistent 
when thinking about indexing & dereferencing.


Besides, I think '[4]foo* foos;' is quite clear.
"array of foo pointers" seems very natural to me.


Ugh. No thanks :-) My brain would short circuit every time I 
see it.


I take it you're not open to considering [4]*foo either?
I feel like there are quite strong argument for it, regarding 
readability & (definition vs operator) consistency.😅


Re: Trying to understand multidimensional arrays in D

2020-12-22 Thread Rekel via Digitalmars-d-learn

On Tuesday, 22 December 2020 at 16:56:18 UTC, Ali Çehreli wrote:

>[4]Foo b; /* an array of four Foos */

[4] already has a meaning. ;)


It  does in that context? Do tell, I'm unaware.

Also, is it possible to move entire thread to a different forum 
group? 😂

This feels more like a discussion fit for 'general'.


Re: Trying to understand multidimensional arrays in D

2020-12-22 Thread ag0aep6g via Digitalmars-d-learn

On Tuesday, 22 December 2020 at 16:56:18 UTC, Ali Çehreli wrote:

On 12/22/20 6:35 AM, ag0aep6g wrote:

> Flip the pointer syntax, too:
>
>  *Foo a; /* a pointer to a Foo */

I am not a language expert but I think that would make D's 
parsing complicated (like C++'s < token) because * already 
means "derefence" in that position. So, the parser would see 
*Foo as a potential compilation error but would have to parse 
forward, etc.


I'm not seriously suggesting changing D's syntax. The current 
syntax is fine with me.


`Foo* a;` is already "complicated", though. `*` can also mean 
multiplication in that position:



struct F
{
F opBinary(string op : "*")(F a) { return F(); }
void opBinary(string op : "+")(int a) { import std.stdio; 
writeln("Hello, world!"); }

}
void main()
{
F Foo;
F a;
Foo* a + 1; /* prints "Hello, world!" */
}


That's a convoluted example, of course. But it shows that the 
compiler already has to look ahead to decide what the `*` means. 
It doesn't just go "That's a type!" when it sees "Foo*".


Re: Trying to understand multidimensional arrays in D

2020-12-22 Thread Ali Çehreli via Digitalmars-d-learn

On 12/22/20 8:56 AM, Ali Çehreli wrote:

> * already means "derefence"

"dereference"

>  > But now we're no longer C-like, I guess.x

That x seems to be due to my fat Emacs fingers.

Ali




Re: Trying to understand multidimensional arrays in D

2020-12-22 Thread Ali Çehreli via Digitalmars-d-learn

On 12/22/20 6:35 AM, ag0aep6g wrote:

> Flip the pointer syntax, too:
>
>  *Foo a; /* a pointer to a Foo */

I am not a language expert but I think that would make D's parsing 
complicated (like C++'s < token) because * already means "derefence" in 
that position. So, the parser would see *Foo as a potential compilation 
error but would have to parse forward, etc.


>[4]Foo b; /* an array of four Foos */

[4] already has a meaning. ;)

> [][4]Foo c; /* a dynamic array of arrays of four Foos each */

I've just learned that the type of [] is void[]. Huh...

> But now we're no longer C-like, I guess.x

Ali



Re: Trying to understand multidimensional arrays in D

2020-12-22 Thread Mike Parker via Digitalmars-d-learn

On Tuesday, 22 December 2020 at 15:31:06 UTC, Rekel wrote:



Don't take that as a defence of changing pointer syntax by the 
way, just noting I think the argument pointers and arrays 
should be defined using a similar syntax is not consistent when 
thinking about indexing & dereferencing.


Besides, I think '[4]foo* foos;' is quite clear.
"array of foo pointers" seems very natural to me.


Ugh. No thanks :-) My brain would short circuit every time I see 
it.


Re: Trying to understand multidimensional arrays in D

2020-12-22 Thread Rekel via Digitalmars-d-learn

On Tuesday, 22 December 2020 at 15:24:04 UTC, Rekel wrote:
The way C syntax handles pointers isn't very consistent to 
begin with imo.
It's strange & and * are prepended to pointer variables for 
example, while indexing is postpended. Leads to stuff like;

(*array_of_pointers_to_arrays[2])[1]

vs

array_of_pointers_to_arrays[2]*[1]


and


(*array_of_pointers[1]).x'

vs

'array_of_pointers[1]*.x'


Don't take that as a defence of changing pointer syntax by the 
way, just noting I think the argument pointers and arrays should 
be defined using a similar syntax is not consistent when thinking 
about indexing & dereferencing.


Besides, I think '[4]foo* foos;' is quite clear.
"array of foo pointers" seems very natural to me.


Re: Trying to understand multidimensional arrays in D

2020-12-22 Thread Rekel via Digitalmars-d-learn

On Tuesday, 22 December 2020 at 14:15:12 UTC, Mike Parker wrote:
[][4]Foo is completely backwards from and inconsistent with the 
pointer declaration syntax. We shouldn't want to intentionally 
introduce inconsistencies.


The way C syntax handles pointers isn't very consistent to begin 
with imo.
It's strange & and * are prepended to pointer variables for 
example, while indexing is postpended. Leads to stuff like;

(*array_of_pointers_to_arrays[2])[1]

vs

array_of_pointers_to_arrays[2]*[1]


and


(*array_of_pointers[1]).x'

vs

'array_of_pointers[1]*.x'


On Tuesday, 22 December 2020 at 14:35:30 UTC, ag0aep6g wrote:

But now we're no longer C-like, I guess.


I think it'd still be quite C-like, same concepts samilar usage.
You're not using 'int foo[]' syntax anymore anyhow.


Re: Trying to understand multidimensional arrays in D

2020-12-22 Thread ag0aep6g via Digitalmars-d-learn

On 22.12.20 15:15, Mike Parker wrote:

On Tuesday, 22 December 2020 at 13:59:54 UTC, Rekel wrote:



I am curious by the way, what do you think of the [][4]Row suggestion 
I gave? In a way you'd have your 🍰 & could eat it too, i think ^^

(Still a strange saying to me)


Currently, D's variable declaration syntax is consistent and, IMO, make 
sense:


Type Name | Extra Tokens | SymbolName
Foo   *   a;
Foo   [4] b;
(Foo  [4])[]  c;

[][4]Foo is completely backwards from and inconsistent with the pointer 
declaration syntax. We shouldn't want to intentionally introduce 
inconsistencies.


Flip the pointer syntax, too:

*Foo a; /* a pointer to a Foo */
  [4]Foo b; /* an array of four Foos */
[][4]Foo c; /* a dynamic array of arrays of four Foos each */

But now we're no longer C-like, I guess.


Re: Trying to understand multidimensional arrays in D

2020-12-22 Thread Mike Parker via Digitalmars-d-learn

On Tuesday, 22 December 2020 at 13:59:54 UTC, Rekel wrote:



I am curious by the way, what do you think of the [][4]Row 
suggestion I gave? In a way you'd have your 🍰 & could eat it 
too, i think ^^

(Still a strange saying to me)


Currently, D's variable declaration syntax is consistent and, 
IMO, make sense:


Type Name | Extra Tokens | SymbolName
Foo   *   a;
Foo   [4] b;
(Foo  [4])[]  c;

[][4]Foo is completely backwards from and inconsistent with the 
pointer declaration syntax. We shouldn't want to intentionally 
introduce inconsistencies.


Re: Trying to understand multidimensional arrays in D

2020-12-22 Thread Rekel via Digitalmars-d-learn

On Tuesday, 22 December 2020 at 07:19:49 UTC, Ali Çehreli wrote:

Let me try the history example:

  Row[4][] history;

Row array (of 4) array.



Fully disagreed: D's array syntax makes me happy; designed 
right. :)


I think i see your point, strange how a change of words makes 
some things make more sense. I'll do my best to think of it like 
that, even if i find it intuïtive. 😅


I am curious by the way, what do you think of the [][4]Row 
suggestion I gave? In a way you'd have your 🍰 & could eat it too, 
i think ^^

(Still a strange saying to me)




Re: Trying to understand multidimensional arrays in D

2020-12-21 Thread Ali Çehreli via Digitalmars-d-learn

On 12/21/20 8:47 PM, Rekel wrote:

> On Monday, 30 January 2017 at 07:33:34 UTC, Ali Çehreli wrote:
>> As others have said, D's array definition is natural because unlike
>> C's inside-out (or is that outside-in?) syntax, it follows from the
>> alias syntax. Replacing History inside main with Matrix[], etc.:
>>
>> History history;// is the same as:
>> Matrix[] history;   // is the same as:
>> Row[4][] history;   // is the same as:
>> int[4][4][] history;
>>
>> Ali
>
> Defending array-notation by giving an example of explicitly not using
> declared aliases makes no sense to me.

Reading 3-year younger Ali's message, I still agree with him. The 
aliases were not given to defend D's array syntax. They were just an 
additional information which I do use occasionally to simplify my code.


> When I define 2d arrays, or index them, I think in row -> column terms

Everybody have their own mental model. Because C, C++, D, three 
languages that I am quite familiar with, don't have 2d arrays, 
personally, I never felt comfortable with that mental model. I don't 
think C's array syntax is left-to-right or right-to-left, it's either 
inside-out or outside-in. As soon as I learned about D's array syntax I 
felt happy. Consistent...


> (often math notation for matrix size being; 'rows x columns'), or more
> generally in big -> small terms, which is clear when using the
> consistent left->right notation, big picture first followed by detail,
> honestly the whole concept of encapsulation;
>
>> History history;
>> Matrix[] history;

Ok.

>> Row[][4] history; // collection of rows, stored in a dynamic array

But that's not consistent. If array syntax is "type followed by square 
bracketed stuff", then your history must be


  Row[4][] history;

  Row[4] -> Four rows

Now, if we call that T, a history of those is

  T[]

Replacing T with Row[4]

  Row[4][] history;

That's what understand from consistency. What other consistent mental 
model is there to accept int[] as an array of ints but when it comes to 
an array of Row[4]s we should write Row[][4]? It's not logical nor 
consistent. It's a remnant of C, where the creator decided to make the 
definition and the use the same (or similar). Well, that did not work 
for me. And the creator agreed in a interview (which I am not motivated 
to search for now) that he might find a better syntax for C array but it 
was too late then.


> At heart however, this declaration design leads to inconsistency.

I disagree and I don't even understand.

>>int[1][2] history; // 1 columm, 2 rows
> vs
>>int last_element = history[1][0] // row 1, column 0
>
> This makes no sense to anyone used to reading left to right, or even
> right to left.

You seem to expect the language to parse history[1][0] as a whole. (?) 
However, history[1] is an expression by itself. There is one thing that 
history[1] returns and that is the second element of that array. [0] is 
and should be applied to whatever history[1] expression produces. Now, 
that's consistent.


> Honestly, reversing reading-order when indexing & declaring is the worst
> idea I could imagine if consistency and readability were your goal.

I argue the complete opposite for the same reason: consistency and 
readability.


> It
> doesn't make more sense because you're reading 'outward', that would
> mean I would have to read both left to right _and_ right to left.

I always read from left to right: T[]. That is the array syntax. And 
arr[i]; that is the array element access syntax. Everything else falls 
into place with those definitions.


> The argument Jonathan M Davis gives in this regard hold no water for me.

Neither to me. I am simple person. Definition: T[], use: arr[i]. Done. :)

>> Like in C/C++, types are mostly read outward from the variable name in
>> D. In both C/C++ and D,

Perhaps because I'm not a native speaker, I have never ever read any 
definition from right-to-left or inside out or outside in.


>> int* foo;
>>
>> is a pointer to an int.

To me, it has always been an "int pointer".

> It's read outward from the variable name, so
>> you get the pointer and then what it points to. Similarly,
>>
>> int** foo;
>>
>> is a pointer to a pointer to an int.

No: "int pointer pointer". :)

> Feel free to read them the way you want, but personally, I read int* foo
> as 'integer pointer', which is not 'outward'.

Thank you! Me too! :)

Let me try the history example:

  Row[4][] history;

Row array (of 4) array.

> just noticed this is how D handles multidimensional arrays

I think that's the source of the disagreements: D does not have 
multidimensional arrays. C and C++ don't have multidimensional arrays 
either.


> It saddens me quite a bit, as I see it as a big design flaw and quite a
> turn-off

Fully disagreed: D's array syntax makes me happy; designed right. :)

> , "unfortunately one that can't be fixed" as Profile Analysis
> put it.

Phew! :)

>> Have a nice & safe christmas!

Same to you! <3

A

Re: Trying to understand multidimensional arrays in D

2020-12-21 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Dec 22, 2020 at 04:47:13AM +, Rekel via Digitalmars-d-learn wrote:
[...]
> Defending array-notation by giving an example of explicitly not using
> declared aliases makes no sense to me.
> When I define 2d arrays, or index them, I think in row -> column terms
> (often math notation for matrix size being; 'rows x columns'), or more
> generally in big -> small terms, which is clear when using the
> consistent left->right notation, big picture first followed by detail,
> honestly the whole concept of encapsulation;

If you really want multidimensional arrays, i.e., arrays that logically
range over an n-dimensional space of indices, not just arrays of arrays
(which is what the array[][]... syntax gives you), I highly recommend
designing your own array type using D's multidimensional array overload
mechanism:

https://dlang.org/spec/operatoroverloading.html#array-ops

This link gives only a 2D example, but it can be generalized to
arbitrary dimensions.  With the proper overloads, you can do
vertical/horizontal slices, subarrays, etc., all with a consistent
syntax:

arr[1, x..y]
arr[i..j, 5]
arr[2..3, 4..6]

See the ndslice package in the mir library for an actual such
implementation.


T

-- 
Why did the mathematician reinvent the square wheel?
Because he wanted to drive smoothly over an inverted catenary road.


Re: Trying to understand multidimensional arrays in D

2020-12-21 Thread Rekel via Digitalmars-d-learn

Small addition, not out of jest;
If plug and play consistency given aliases is required (which 
seems pointless, as they exit to be used), the best solution, 
which would avoid indexing inconsistency given regular reading 
order, would be the following;


alias Row = [3]int;
[1][2][3]int history;
int last_element = history[0][1][2];
[1][2]Row history;
int last_element = history[0][1][2];
Row last_row = history[0][1];

This would be consistent, and readable.


Re: Trying to understand multidimensional arrays in D

2020-12-21 Thread Rekel via Digitalmars-d-learn

On Monday, 30 January 2017 at 07:33:34 UTC, Ali Çehreli wrote:
As others have said, D's array definition is natural because 
unlike C's inside-out (or is that outside-in?) syntax, it 
follows from the alias syntax. Replacing History inside main 
with Matrix[], etc.:


History history;// is the same as:
Matrix[] history;   // is the same as:
Row[4][] history;   // is the same as:
int[4][4][] history;

Ali


Defending array-notation by giving an example of explicitly not 
using declared aliases makes no sense to me.
When I define 2d arrays, or index them, I think in row -> column 
terms (often math notation for matrix size being; 'rows x 
columns'), or more generally in big -> small terms, which is 
clear when using the consistent left->right notation, big picture 
first followed by detail, honestly the whole concept of 
encapsulation;



History history;
Matrix[] history;
Row[][4] history; // collection of rows, stored in a dynamic 
array (top level), each containing 4 (in detail).
int[][4][4] history; // collection of integers, stored in a 
dynamic array (top level), containing 4 rows (->middle level->) 
of 4 columns (in detail),


Of course, one can also prefer storing in columns, instead of 
rows, even glsl uses column-major order, just change 'Row' to 
'Column' and you're set.
My argument here of course rests on outside->in thinking, which 
one can reverse consistently. I would be fine with that.


At heart however, this declaration design leads to inconsistency.


   int[1][2] history; // 1 columm, 2 rows

vs

   int last_element = history[1][0] // row 1, column 0


This makes no sense to anyone used to reading left to right, or 
even right to left.
Honestly, reversing reading-order when indexing & declaring is 
the worst idea I could imagine if consistency and readability 
were your goal. It doesn't make more sense because you're reading 
'outward', that would mean I would have to read both left to 
right _and_ right to left.


The argument Jonathan M Davis gives in this regard hold no water 
for me.
Like in C/C++, types are mostly read outward from the variable 
name in D. In both C/C++ and D,


int* foo;

is a pointer to an int. It's read outward from the variable 
name, so you get the pointer and then what it points to. 
Similarly,


int** foo;

is a pointer to a pointer to an int.


Feel free to read them the way you want, but personally, I read 
int* foo as 'integer pointer', which is not 'outward'. Your 
argument is only based on personal reading preference, but with 
it you remove indexing consistency & introduce boustrophedon.


You don't even always have the variable name;

... = new int[1][2]

vs

... = new int[][](2, 1)


If you were to ask someone with no prior coding experience how to 
access a predefined declaration, given a onedimensional 
explanation, I'm certain they would default to standard western 
reading order, no matter the presence of a variable name.


I'm surprised this thread is 3 years old by the way, sorry for 
that, just noticed this is how D handles multidimensional arrays 
(I may add a note about this to the tour suggestions).
It saddens me quite a bit, as I see it as a big design flaw and 
quite a turn-off, "unfortunately one that can't be fixed" as 
Profile Analysis put it.



Have a nice & safe christmas!
- Rekel, the disproportionally active forum . . . person (sorry)


Re: Trying to understand multidimensional arrays in D

2017-01-29 Thread Ali Çehreli via Digitalmars-d-learn

On 01/25/2017 05:47 PM, Profile Anaysis wrote:

> a 4x4 matrix and have a history of it. Just
> n 4x4 matrices but each matrix is a fixed size but there can be an
> arbitrary(dynamic) number.

I don't think using aliases is recommended yet. It can simplify things a 
lot:


import std.stdio;

alias Row = int[4];
alias Matrix = Row[4];
alias History = Matrix[];

Row makeRow(int value) {
Row row;
row = value;// Special array syntax; all elements are now 'value'
return row;
}

Matrix makeMatrix() {
Matrix matrix;
foreach (int i, ref row; matrix) {
row = makeRow(i + 1);
}
return matrix;
}

void main() {
History history;
foreach (i; 0..3) {
history ~= makeMatrix();
}
writeln(history);
}

As others have said, D's array definition is natural because unlike C's 
inside-out (or is that outside-in?) syntax, it follows from the alias 
syntax. Replacing History inside main with Matrix[], etc.:


History history;// is the same as:
Matrix[] history;   // is the same as:
Row[4][] history;   // is the same as:
int[4][4][] history;

Ali



Re: Trying to understand multidimensional arrays in D

2017-01-26 Thread Ivan Kazmenko via Digitalmars-d-learn
On Thursday, 26 January 2017 at 05:20:07 UTC, Profile Anaysis 
wrote:
(On the contrary, declarations in C or C++ looks rather 
unintuitive from this perspective: `T a[4][5][6]` is means 
that `a` is an array of 4 arrays of 5 arrays of 6 arrays of 
`T`.  Note how we have to read left-to-right but then wrap 
around the string to get the meaning.)


lol, I don' tknow what the last sentence means. wrap around the 
string? Do you mean look at the variable?


For me the interpretation above is the most logical because it 
is a sequential operation in my mind, if you will. x of y of z 
and the chain can be cut off anywhere and the interpretation 
still be the same.


This means that in `T a[4][5][6]`, the type `T[4][5][6]` is 
spread on both sides of the variable name `a`.  In the 
interpretation,

"`a` is an array of 4 arrays of 5 arrays of 6 arrays of `T`",
note that 4, 5 and 6 are from the right side but T is from the 
left side.  That's what I meant by wrap around.


Re: Trying to understand multidimensional arrays in D

2017-01-26 Thread Jonathan M Davis via Digitalmars-d-learn
On Thursday, January 26, 2017 05:44:04 Profile Anaysis via Digitalmars-d-
learn wrote:
> I am using static arrays because the size of the matrix is fixed.
> I need to allocate them though because that is what my
> matrix_history contains.

If I understood correctly, you want a dynamic array of static arrays where
the static array is therefore an entry in your "matrix history." That does
not require that you allocate a static array. It just requires that you
allocate the dynamic array of static arrays. For instance, if you had an
integer instead of a matrix, you would have something like

int[] arr;

and when you appended to it, you would just append the value. e.g.

arr ~= 42;
arr ~= 77;
arr ~= 9;

No allocation of the values is required. The dynamic array may very well do
some reallocating to fit the new values (depending on its current capacity),
but the values themselves are not allocated. So, if you have a dynamic array
of static arrays

int[4][4][] arr;

then you just append each static array. e.g.

int[4][4] value;
// fill in value...

arr ~= value;

or

arr ~= [[9, 9, 9, 9], [7, 7, 7, 7], [2, 2, 2, 2], [3, 3, 3, 3]];

Again. You're not allocating the values that you're appending at all. At
most, the dynamic array ends up being reallocated to make room for more
elements.

- Jonathan M Davis



Re: Trying to understand multidimensional arrays in D

2017-01-26 Thread Mike Parker via Digitalmars-d-learn
Sorry. I mistyped some of my examples. Obviously dropped some 
news:


auto a = new int[](4);
auto b = new int[][](4);

And the static arrays should be:
int[4] c;
int[][4] d;

And I would also like managed to overlook there is no static 
array in sight here:


auto y = new int[1][2][][](3,4);

The 1 and 2 are not creating static arrays. They are dynamic 
arrays. The following are exactly the same:


auto a1 = new int[](2);
auto a2 = new int[2];

The syntax in a2 is the original syntax for allocating space for 
dynamic arrays. The () was added later.


The point I made about changing the declaration of x remains.


Re: Trying to understand multidimensional arrays in D

2017-01-26 Thread Mike Parker via Digitalmars-d-learn
On Thursday, 26 January 2017 at 05:50:03 UTC, Profile Anaysis 
wrote:


It is inconsistent with dynamic arrays and mixing them creates 
a mess in the order of indices.


I best someone was asleep at the wheel when programming the 
code for static arrays. (probably someone different than who 
programmed the dynamic arrays)


This is a bug IMO.(unfortunately one that can't be fixed ;/)


No, there's no inconsistence and there's no bug. Shorten things 
down a bit:


```
auto x = new int[][](3,4);
auto y = new int[3][](4);
writefln("%s, %s", x[0].length, y[0].length);
```
This will print 4, 3. Why?

auto a = int[](4);

In this case, a is an array of int. The allocation makes space 
for 4 values of type int.


auto b = int[][](4);

Here, b is an array of int[]. The allocation makes space for 
values of type int[].


The following are the equivalent declarations for static arrays:

auto c = int[4];
auto d = int[][4];

In other words  int[][4] is the static equivalent of new 
int[][](4).


Following from that:

auto e = new int[][](4, 3);

This creates an array of 4 values of type int[], each of which is 
an array that holds 3 values of type int. The static equivalent:


auto f = int[3][4];

So based on that, you should be able to see that the problem is 
not in the implementation of static arrays in D, but a mismatch 
in your declarations.


auto x = new int[][][][](1,2,3,4);
auto y = new int[1][2][][](3,4); // Does not match declaration of 
x


To get what you want, change the declaration of x:

auto x = new int[][][][](4, 3, 2, 1);


Re: Trying to understand multidimensional arrays in D

2017-01-25 Thread Profile Anaysis via Digitalmars-d-learn
On Thursday, 26 January 2017 at 03:02:32 UTC, Jonathan M Davis 
wrote:
On Thursday, January 26, 2017 01:47:53 Profile Anaysis via 
Digitalmars-d- learn wrote:

 [...]


Like in C/C++, types are mostly read outward from the variable 
name in D. In both C/C++ and D,


[...]


Actually, I think the notation is simply wrong.


// Matrix order testing
auto x = new int[][][][](1,2,3,4);
auto y = new int[1][2][][](3,4);

for(int i = 0; i < 1; i++)
for(int j = 0; j < 2; j++)
for(int k = 0; k < 3; k++)
for(int l = 0; l < 4; l++)   
{
x[i][j][k][l] = i*j*k*l;
//x[l][k][j][i] = i*j*k*l;

//y[i][j][k][l] = i*j*k*l;
//y[l][k][j][i] = i*j*k*l;
y[k][l][j][i] = i*j*k*l;
}


It is inconsistent with dynamic arrays and mixing them creates a 
mess in the order of indices.


I best someone was asleep at the wheel when programming the code 
for static arrays. (probably someone different than who 
programmed the dynamic arrays)


This is a bug IMO.(unfortunately one that can't be fixed ;/)




Re: Trying to understand multidimensional arrays in D

2017-01-25 Thread Profile Anaysis via Digitalmars-d-learn
On Thursday, 26 January 2017 at 03:02:32 UTC, Jonathan M Davis 
wrote:
On Thursday, January 26, 2017 01:47:53 Profile Anaysis via 
Digitalmars-d- learn wrote:

 [...]


Like in C/C++, types are mostly read outward from the variable 
name in D. In both C/C++ and D,


[...]


Thanks. I'll just have to play around with them a bit until it 
sinks in. I think my problem was declaring them wrong which would 
always lead to weird errors.


I am using static arrays because the size of the matrix is fixed. 
I need to allocate them though because that is what my 
matrix_history contains.


I guess I can do that with new int[n][n] type of thing? (I think 
I tried that before.


Anyways, probably would work fine now but I already move don to 
wrapping it in a struct. It provides more flexibility in my case.





Re: Trying to understand multidimensional arrays in D

2017-01-25 Thread Profile Anaysis via Digitalmars-d-learn

On Thursday, 26 January 2017 at 02:29:07 UTC, Ivan Kazmenko wrote:
On Thursday, 26 January 2017 at 01:47:53 UTC, Profile Anaysis 
wrote:

does this mean that have

int[][4][4] matrix_history;

backwards?

int[4][4][] matrix_history;

this creates even a more set of problems.


In short, you are right, `int[4][4][]` is a dynamic array of 
`int[4][4]`.  In turn, `int[4][4]` is a static length-4 array 
of `int[4]`, and that is a static length-4 array of `int`.  
It's quite logical once you learn how to read it: if T is a 
type, then T[] is a dynamic array of that type, and T[4] is a 
static length-4 array of that type.


So, if I have `int[2][5][7] a;` somewhere, the very last 
element is `a[6][4][1]`.  If you are inclined to think in terms 
of this difference, the simple rule of thumb would be that the 
order of dimensions in the declaration is reversed.


Thanks, knowing the last element is important ; Basically I just 
need to know the proper index. For me, having the array declared 
in symbolic form that matches the indexing, like in C/C++, is 
quicker, easier to remember, and harder to forget. I don't really 
care too much beyond that. They could be declared any way... but 
I find myself getting confused in D because of little things like 
this that don't carry over while almost everything else is.



Also, note that if you want to have, for example, a dynamic 
array of 5 dynamic arrays of the same length 7 (modeling a C 
rectangular array, or a D static array, but with possibility to 
change the length of each row, as well as the number of rows), 
you would go with

`auto a = new int [] [] (5, 7);` (initialization)
The static array of 5 static arrays of length 7 is still
`int [7] [5] a;` (type declaration)
So the reverse only happens in type declarations.




(On the contrary, declarations in C or C++ looks rather 
unintuitive from this perspective: `T a[4][5][6]` is means that 
`a` is an array of 4 arrays of 5 arrays of 6 arrays of `T`.  
Note how we have to read left-to-right but then wrap around the 
string to get the meaning.)


lol, I don' tknow what the last sentence means. wrap around the 
string? Do you mean look at the variable?


For me the interpretation above is the most logical because it is 
a sequential operation in my mind, if you will. x of y of z and 
the chain can be cut off anywhere and the interpretation still be 
the same.


Since I am a native speaker of English, which is a left to right 
language, it just makes sense. I, am, of coursed biased because I 
started with C/C++ rather than D.




Additionally, reading about various kinds of arrays in D might 
help:

https://dlang.org/spec/arrays.html

And more in-depth material about array slicing:
http://dlang.org/d-array-article.html

Ivan Kazmenko.





Re: Trying to understand multidimensional arrays in D

2017-01-25 Thread Jonathan M Davis via Digitalmars-d-learn
On Thursday, January 26, 2017 01:47:53 Profile Anaysis via Digitalmars-d-
learn wrote:
> I'm a bit confused by how D does arrays.
>
> I would like to create a array of matrices but I do not seem to
> get the correct behavior:
>
>  int[][4][4] matrix_history;

Like in C/C++, types are mostly read outward from the variable name in D. In
both C/C++ and D,

int* foo;

is a pointer to an int. It's read outward from the variable name, so you get
the pointer and then what it points to. Similarly,

int** foo;

is a pointer to a pointer to an int. In C/C++, a static array would be
written like

int arr[4][3];

and again, it's read outward from the type. It's a static array of 4 static
arrays of 3 ints. This gets increasingly confusing as the types get more
complicated, but it's critical for understanding how function pointers are
written in C/C++. For D, it's a lot less critical, because we have a cleaner
function pointer declaration syntax, but the same basic rules mostly apply
(const, immutable, and shared is where they start breaking the rules a bit,
but they're pretty straightforward and consistent with just pointers and
arrays). That

int arr[4][3];

in C/C++ can then be accessed like so

arr[3][2] = 5;

and that would get the 3rd element in the first array and the second element
in the second array without exceeding the bounds of the array. D follows the
same declaration rules except that it has the array bounds all on the
left-hand side of the variable. So, in C/C++, you have

int arr[4][3];

whereas in D, the same array would be

int[3][4] arr;

and you would still access it like so

arr[3][2] = 5;

without exceeding the bounds of the array, whereas

arr[2][3] = 5;

_would_ exceed the bounds of the array, because the second array has 3
elements in it, and that asks for the 4th.

This tends to be very confusing at first, because most folks usually expect
the indices to always in the same order, when they're not. They are so long
as the sizes is always on the right-hand side, which occurs with dynamic
arrays, but in D, static arrays go on the left. C/C++ would have the exact
same ordering problem as D if it put the sizes on the left, because it uses
basically the same rules for how types are written. But they put it on the
right, separating from the type, which makes the indices clearer but splits
the type in two. So, both approaches have their pros and cons.

In any case, the idea that the type is read outward from the variable name
extends to types in general. In particular, if you have

int[][4][4] arr;

as in your example, you have a static array of 4 static arrays of 4 dynamic
arrays of int. You can append to the innermost static array

arr[3][3] ~= [1, 2, 3];

but you can't append to arr. If you want a dynamic array of static arrays,
then you need to do

int[4][4][] arr;

Then you can append a 4x4 static array to arr. However, your attempts at
creating a static array were not actually creating static arrays.

auto arr = new int[4];

and

auto arr = new int[](4);

both allocate a dynamic array of length 4. The code semantics are identical.
However, once we go beyond one dimension, it starts mattering - and getting
confusing. Take this

auto arr = new int[][](4, 5);
static assert(is(typeof(arr) == int[][]));
assert(arr.length == 4);

arr is a dynamic array of length 4 that contains dynamic arrays of length 5
of int. This on the other hand

auto arr = new int[4][](5);
static assert(is(typeof(arr) == int[4][]));
assert(arr.length == 5);

makes it so that arr is dynamic array of length 5 that contains static
arrays of length 4 of int.

auto arr = new int[4][5];
static assert(is(typeof(arr) == int[4][]));
assert(arr.length == 5);

has the exact same semantics. So, the right-most number is always the length
of the outer, dynamic array, and whether the interior is more dynamic arrays
or static arrays depends on whether the numbers are between the brackets or
the parens.

Another thing to note is that when you have int[][], it is a dynamic array,
whereas int[4][4] is a static array. So, whenever you see the compiler give
you the type int[][], it's talking about a dynamic array, not a static
array. The numbers have to be there for it to be a static array. When
looking at the type of an array (as opposed to a expression using new),
numbers between the subscripts mean a static array, whereas a lack of
numbers means a dynamic array, and the type of a dynamic array does not
change depending on its length.

Also, even if you had declared matrix_history correctly

int[4][4][] matrix_history;

this code would be wrong

> matrix_history ~= new int[][](4,4);

because int[][](4, 4) is allocating a dynamic array of dynamic arrays of
ints, not a static array of 4 static arrays of 4 ints.

In addition, AFAIK, you can't just new up a static array of 4 static arrays
of int. You can new up dynamic arrays but not static arrays. The static
arrays need to be in something to be on the heap. But that's not really what
you wanted 

Re: Trying to understand multidimensional arrays in D

2017-01-25 Thread Ivan Kazmenko via Digitalmars-d-learn
On Thursday, 26 January 2017 at 01:47:53 UTC, Profile Anaysis 
wrote:

does this mean that have

int[][4][4] matrix_history;

backwards?

int[4][4][] matrix_history;

this creates even a more set of problems.


In short, you are right, `int[4][4][]` is a dynamic array of 
`int[4][4]`.  In turn, `int[4][4]` is a static length-4 array of 
`int[4]`, and that is a static length-4 array of `int`.  It's 
quite logical once you learn how to read it: if T is a type, then 
T[] is a dynamic array of that type, and T[4] is a static 
length-4 array of that type.


So, if I have `int[2][5][7] a;` somewhere, the very last element 
is `a[6][4][1]`.  If you are inclined to think in terms of this 
difference, the simple rule of thumb would be that the order of 
dimensions in the declaration is reversed.


Also, note that if you want to have, for example, a dynamic array 
of 5 dynamic arrays of the same length 7 (modeling a C 
rectangular array, or a D static array, but with possibility to 
change the length of each row, as well as the number of rows), 
you would go with

`auto a = new int [] [] (5, 7);` (initialization)
The static array of 5 static arrays of length 7 is still
`int [7] [5] a;` (type declaration)
So the reverse only happens in type declarations.

(On the contrary, declarations in C or C++ looks rather 
unintuitive from this perspective: `T a[4][5][6]` is means that 
`a` is an array of 4 arrays of 5 arrays of 6 arrays of `T`.  Note 
how we have to read left-to-right but then wrap around the string 
to get the meaning.)


Additionally, reading about various kinds of arrays in D might 
help:

https://dlang.org/spec/arrays.html

And more in-depth material about array slicing:
http://dlang.org/d-array-article.html

Ivan Kazmenko.



Trying to understand multidimensional arrays in D

2017-01-25 Thread Profile Anaysis via Digitalmars-d-learn

I'm a bit confused by how D does arrays.

I would like to create a array of matrices but I do not seem to 
get the correct behavior:


int[][4][4] matrix_history;

What I would like is to have a 4x4 matrix and have a history of 
it. Just n 4x4 matrices but each matrix is a fixed size but there 
can be an arbitrary(dynamic) number.


I would like, for example,

matrix_history[0] to be the first 4x4 matrix,
matrix_history[1] to be the second 4x4 matrix,
...

and I would, in fact, like to be able to append a matrix like

matrix_history ~= some_4x4matrix.

I try to assign like

matrix_history[total-1] = new int[][](8,8);

or append

matrix_history ~= new int[][](4,4);

but the append fails with

Error: cannot append type int[][] to type int[][4][4]

which is confusing because the type per entry in the matrix 
history is of type int[][].


e.g., I could wrap the int[][] in a struct and then just have a 
singular array of these matrices and, to me, the logic should be 
the same. e.g.,


struct matrix
{
int[4][4] data;
}

then

matrix[] matrix_history.

and

matrix_history ~= new matrix;

so, the logic should be the same between two. This method works 
but the more direct method doesn't seem to.


If I do

auto x = matrix_history[0];

x is not a int[4][4] but of type int[4](as reported by the 
debugger), which is very confusing.


it seems that the way D indexes multidimensional arrays is not 
logical nor consistent from my perspective.


auto x = matrix_history[0] returns an array of size 4.
auto x = matrix_history[0][0] returns an 2d array of size 4x4.
auto x = matrix_history[0][0][0] returns an int(as expected).


does this mean that have

int[][4][4] matrix_history;

backwards?

int[4][4][] matrix_history;

this creates even a more set of problems.

I guess I will have to revert to wrapping the matrix in a struct 
to get the natural extension of single arrays unless someone can 
clue me in on what is going on.