Delphi arrays have a few quirks (as mentionned here on TURBU f.i.), which arise from there being actually four different types arrays in Delphi, with limited interoperability:
- array [low..high] of TSomeType: the bounded array, a value type, useful for structures, fixed-size vectors & matrices, and also piggybacked by the constant arrays.
- array of TSomeType: the dynamic array, a reference type, almost all the time, but not strictly usable as a reference type (see below).
- array of const: the open array, actually an array of TVarRec managed with compiler magic.
- String/AnsiString: arrays of Char/AnsiChar, behaves like a value type, implemented as a reference with copy-on-write.
Dyanamic array half-bakedness
Thing is, all of these arrays have pitfalls of their own, the dynamic array f.i. is a classical trap, and you don’t really want to use it as anything else but a field or local variable. Why? Because it is a reference type which the RTL treats as a value type, f.i.
var a, b : array of Integer; SetLength(a, 1); a := 1; b := a; b := 2; // after that a is 2 SetLength(a, 2); // that effectively decouples a and b a := 3; // after that b is still 2
In other words, the dynamic arrays stays a reference as long as you don’t change its size… If you wonder why using TBytes for holding binary buffer is frowned upon, that is one of the reasons. Things quickly turn to mush if pass a dynamic array around functions (think Java-like deep vs shallow copy mess).
This could all be solved and improved by providing RTL functions that would treat dynamic arrays as a reference type, and ideally by having a new flavor of dynamic arrays with copy-on-write semantics (like what String does for Char, but that would allow any element type).
Though arguably, once you have that new dynamic array, the old dynamic array as a reference type only value would be useful for optimization (to bypass the reference count check when writing to the elements of the array).
Another issue, is that there is little to no cross-array type support, f.i. you can’t initialize a dynamic arrays by assigning to it a constant array f.i., or have inline or default values for typed array parameters, etc.
Why am I mentioning all this? Because I’m currently investigating array support in DWS. Currently DWS doesn’t have dynamic arrays (apart from COM variant arrays), that isn’t too problematic in a scripting language, as you usually don’t code basic containers script-side, and once you have various base TXxxList, you don’t really “need” dynamic arrays, but still, they would be convenient is a variety of situations.
Having more “cooperative” array types is high on the DWS priority list, as uncooperative array types are a recurring PITA in Delphi. Ideally, this cooperativeness would extend to containers (being able to initialize a dynamic array from an enumerator, etc.). But I also don’t want to fork a whole new incompatible Pascal language branch on that aspect, just for DWS.
Hopefully, there will be some debate on this issue, and good ideas may be flown around. ^_^