On Sunday, 2 August 2020 at 02:00:46 UTC, Andy Balba wrote:
On Saturday, 1 August 2020 at 22:00:43 UTC, Ali Çehreli wrote:
On 8/1/20 12:57 PM, Andy Balba wrote:
> On Saturday, 1 August 2020 at 00:08:33 UTC, MoonlightSentinel
wrote:
>> On Friday, 31 July 2020 at 23:42:45 UTC, Andy Balba wrote:
>>> How does one initialize c in D ?
>>
>> ubyte[3][4] c = [ [5, 5, 5], [15, 15,15], [25, 25,25], [35,
35,35] ];
> I'm a D newbie. moving over from C/C++, and I'm really
finding it hard
> to adjusting to D syntax, which I find somewhat cryptic
compared to C/C++.
That's surprising to me. I came from C++03 year ago but
everything in D was much better for me. :)
I wanted to respond to your question yesterday and started
typing some code but then I decided to ask first: Do you
really need a static array? Otherwise, the following is a
quite usable 2D array:
ubyte[][] c = [ [5, 5, 5], [15, 15,15], [25, 25,25], [35,
35,35] ];
However, that's quite different from a ubyte[3][4] static
array because 'c' above can be represented like the following
graph in memory. (Sorry if this is already known to you.)
c.ptr --> | .ptr | .ptr | .ptr | .ptr |
| | | |
. . | --> | 35 | 35 | 35 | 35 |
etc. etc. --> | 25 | 25 | 25 | 25 |
In other words, each element is reached through 2 dereferences
in memory.
On the other hand, a static array consists of nothing but the
elements in memory. So, a ubyte[3][4] would be the following
elements in memory:
| 5 | 5 | ... | 35 | 35 |
One big difference is that static arrays are value types,
meaning that all elements are copied e.g. as arguments during
function calls. On the other hand, slices are copied just as
fat pointers (ptr+length pair), hence have reference semantics.
Here are some ways of initializing a static array. This one is
the most natural one:
ubyte[3][4] c = [ [5, 5, 5], [15, 15,15], [25, 25,25], [35,
35,35] ];
Yes, that works! :) Why did you need to cast to begin with?
One reason may be you had a value that could not fit in a
ubyte so the compiler did not agree. (?)
This one casts a 1D array as the desired type:
ubyte[3][4] c = *cast(ubyte[3][4]*)(cast(ubyte[])[ 5, 5, 5,
15, 15, 15, 25, 25, 25, 35, 35, 35 ]).ptr;
The inner cast is required because 5 etc. are ints by-default.
There is std.array.staticArray as well but I haven't used it.
Ali
Although not detailed in my original question, in my actual app
I have array ubyte [1000][3] Big which consists of research
data I obtained,
and from which I want to randomly select 4 observations to
construct
ubyte c[ ][ ].
i.e. construct c= [ Big[r1][3], Big[r2][3], Big[r3][3],
Big[r4][3] ]
where r1, r2, r3 and r4 are 4 random integers in 0..1001
Being a D newbie, my naive way of doing this was to declare c
using:
ubyte[3][4] c= [ Big[r1][3], Big[r2][3], Big[r3][3], Big[r4][3]
]
Obviously, I want to learn how to this the smart D way, but I
not smart enough at this point.
You haven't said anything about efficiency because if you care
and your arrays are rather big, you better go with
https://github.com/libmir/mir-algorithm as mentioned above. It
might be a little finicky at the start but this post:
https://tastyminerals.github.io/tasty-blog/dlang/2020/03/22/multidimensional_arrays_in_d.html should get you up to speed.
Keep in mind that std.array.staticArray is not efficient for
large arrays.
If you want to stick to standard D, I would not initialize a 2D
array because it is just cumbersome but rather use a 1D array and
transform it into 2D view on demand via ".chunks" method. Here is
an example.
import std.range;
import std.array;
void main() {
int[] arr = 20.iota.array;
auto arr2dView = arr.chunks(5);
}
Should give you
┌ ┐
│ 0 1 2 3 4│
│ 5 6 7 8 9│
│10 11 12 13 14│
│15 16 17 18 19│
└ ┘
whenever you need to access its elements as arr.chunks(5)[1][1 ..
3] --> [6, 7].