How use two-dimensional array

public func two_array(): async Text{
let arr = Array.init<[var Nat]>(2, Array.init(2,0));
arr[0][0] := 1;
arr[1][0] := 2;
Debug.print(“0,0:” # Nat.toText(arr[0][0]));
Debug.print(“1,0:” # Nat.toText(arr[1][0]));
“why !!!”
};

it print:
[Canister rrkah-fqaaa-aaaaa-aaaaq-cai] 0,0:2
[Canister rrkah-fqaaa-aaaaa-aaaaq-cai] 1,0:2

I want:
[Canister rrkah-fqaaa-aaaaa-aaaaq-cai] 0,0:1
[Canister rrkah-fqaaa-aaaaa-aaaaq-cai] 1,0:2

why???

Because both inner arrays are actually the same array. Ie arr[0] == arr[1], in terms of identity.

The reason for this is that the second parameter of Array.init<T> is the value with which to initialize your array. What you pass in there is - from the point of view of Array.init - static, and not reevaluated every time.

Your code is equivalent to the following, which makes the error more clear:

let inner = Array.init<Nat>(2, 0);
let outer = Array.init<[var Nat]>(2, inner);
// ...

What you need to do is to make sure that each member of the outer array is initialized with a separate instance of an array. Can be done eg like this:

let ary = Array.tabulateVar<[var Nat]>(
  2,
  func(i : Nat) : [var Nat] {
    return Array.init<Nat>(2, 0);
  },
);

Array.tabulateVar will call the provided function for every member, and use its returns value to populate the array.

Or with a simple for loop:

let ary = Array.init<[var Nat]>(2, Array.init<Nat>(2, 0));
for (i in Iter.range(0, 1)) {
  ary[i] := Array.init<Nat>(2, 0);
};

Where the loop ensures that each member of the outer array is a separate array.

3 Likes

I get , thank you very much