1

I'm writing a smart contract and want to use Arrays to manipulate data, but looking at the AssemblyScript docs, I'm not sure the best way to proceed.

It seems fine to me to just use:

let testData:string[] = []

but when I consulted the assemblyscript docs, there are three recommended ways to create an Array:

// The Array constructor implicitly sets `.length = 10`, leading to an array of
// ten times `null` not matching the value type `string`. So, this will error:
var arr = new Array<string>(10);
// arr.length == 10 -> ERROR

// To account for this, the .create method has been introduced that initializes
// the backing capacity normally but leaves `.length = 0`. So, this will work:
var arr = Array.create<string>(10);
// arr.length == 0 -> OK

// When pushing to the latter array or subsequently inserting elements into it,
// .length will automatically grow just like one would expect, with the backing
// buffer already properly sized (no resize will occur). So, this is fine:
for (let i = 0; i < 10; ++i) arr[i] = "notnull";
// arr.length == 10 -> OK

When would I want to use one type of instantiation over another? Why wouldn't I just always use the version I presented in the beginning?

2 Answers2

1

Nothing wrong with the array literal approach. It is basically equivalent to

let testData = new Array<string>();

However, sometimes you know what the length of the array should be and in such cases, preallocating the memory using Array.create is more efficient.

berryguy
  • 1,144
  • 3
  • 4
1

UPDATE

With this PR Array.create deprecated and should not be used anymore.

OLD ANSWER

let testData:string[] = []

semantically the same as

let testData = new Array<string>()

AssemblyScript doesn't support preallocated sparse arrays (arrays with holes) for reference elements which not explicitly declared as nullable like:

let data = new Array<string>(10);
data[9] = 1; // will be compile error

Instead you could use:

let data = new Array<string | null>(10);
assert(data.length == 10); // ok
assert(data[0] === null); // ok

or Array.create but in this case your length will be zero. Array.create is actually just reserve capacity for backing buffer.

let data = Array.create<string>(10);
assert(data.length == 0); // true

For plain (non-reference) types you could use usual way without care about nullabe or creating array via Array.create:

let data = new Array<i32>(10);
assert(data.length == 10); // ok
assert(data[0] == 0); // ok
MaxGraey
  • 351
  • 2
  • 6
  • Thanks for the thorough answer! > `Array.create` is actually just reserve capacity for backing buffer. This makes much more sense now. What's the difference between explicitly setting something to nullable with strings and the case where it seems to become an array of i32 typed zeroes? – Peter DePaulo Sep 19 '19 at 20:19