module main;
void changeContent(Arr)(Arr arr)
{
arr[] = 10;
}
void changeSizeAndContent(Arr)(Arr arr)
{
enum RESIZE = 10;
arr.length = RESIZE;
int c = RESIZE;
foreach (ref e; arr)
{
e = c--;
}
}
void main()
{
import std.container.array;
import std.stdio;
auto builtinArr = [1, 2, 3, 4];
changeContent(builtinArr);
writeln(builtinArr); // prints [10, 10, 10, 10]
changeSizeAndContent(builtinArr);
writeln(builtinArr); // prints [10, 10, 10, 10]
auto stdArr = Array!int([1, 2, 3, 4]);
changeContent(stdArr);
writeln(stdArr); // prints Array!int(Payload(4, [10, 10, 10, 10]))
changeSizeAndContent(stdArr);
writeln(stdArr); // prints Array!int(Payload(10, [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]))
}
For builtin array, when reallocation happens, we basically get a new array. Any changes to it do not affect the original.
*On the other hand, when reallocation doesn't happen, the original can be modified.
For std Array, the payload is always shared, it works as if we are passing "ref T[]" all the time, except when it's reassigned with: arr = Array!int([]) -- probably the reason why no opAssign(R)(R range) is implemented for std Array, so that the coder understands new payload is being created?
I assume it's possible to implement std Array to work more like the builtin - new payload is created if it grows over capacity, which will make "ref" actually useful here. Perhaps also have Array.opSlice return an Array, instead of a "view" that can't be augmented.