how to append (ref) int[] to int[][]?

Simen Kjærås simen.kjaras at gmail.com
Mon Jun 8 06:42:44 UTC 2020


On Monday, 8 June 2020 at 06:13:36 UTC, mw wrote:
> Hi,
>
> I have this program:
> ----------------------------------------------------
> import std.stdio;
>
> void f(ref int[] arr) {
>         arr ~= 3;
> }
>
> void main() {
>         int[][] arrs;
>         int[] arr;
>         foreach (i; 0 .. 3) {
>                 arr = new int[0];
>                 arrs ~= arr; //(a) [[], [], []]
>                 f(arr);
>                 // arrs ~= arr; //(b) [[3], [3], [3]]
>         }
>
>         writeln(arrs);
> }
> ----------------------------------------------------
>
> This program will print out [[], [], []].
>
> If I comment out (a), and use (b), it will print out [[3], [3], 
> [3]]
>
> So based on this behavior, looks like "~=" will append a copy 
> of `arr`; but what I really want in (a) is append `ref arr` and 
> output [[3], [3], [3]], i.e. the real `arr` be appended instead 
> of its copy.
>
> I have to say this semantics surprised me.
>
> I tried to change arrs' decl to:
>
>     (ref (int[]))[] arrs;  // the intended semantics I want
>
> But I got compiler error out: "found ( when expecting function 
> literal following ref".
>
> 1) I'm wondering how to achieve what I want? and
> 2) why "~=" here will append a copy rather than the real `arr` 
> itself to arrs?

Arrays (technically, slices) in D are essentially this struct:

struct Array(T) {
     T* ptr;
     size_t length;
     // operator overloads
}

So when you have int[][], each element of the outer array is an 
Array!int. These, as simple structs, are copied about, so that 
changing one does not change another.

The simple solution here is to call f not on arr, but on 
arrs[$-1] (the last element of arrs). If that is not possible you 
will need arrs to be an int[]*[].

--
   Simen


More information about the Digitalmars-d-learn mailing list