All the Delphi arrays…

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[0] := 1;
    b := a;
    b[0] := 2; // after that a[0] is 2
    SetLength(a, 2); // that effectively decouples a and b
    a[0] := 3; // after that b[0] 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).

Array interoperability

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. ^_^

7 thoughts on “All the Delphi arrays…

  1. Great article! I do not often arry based work but it’s really worth to read it.

    I think in the following line there is a typo:
    b[0] := 2; // after that a[1] is 2

    shouldn’t it be
    b[0] := 2; // after that a[0] is 2 ??

    Regards,
    Hubert

  2. @Eric I saw that DWS now support for … to/downto … step … do AWESOME!! one more thing that would be Extremely useful is a single block for:
    try

    except

    finally

    end;
    that in the background will of course call:
    try
    try

    except

    end;

    finally

    end;
    I believe it has value, don’t you?!

  3. It’s imho of low priority, as in a script exception handling are rarer encounters than in a “full-blown” language, and you often can’t rely on the scripts user to cleanup their resources in the first place ^_^
    DWScript is also managing the release of objects automatically, so there aren’t as many try..finally needed as in Delphi code f.i.

  4. @Dorin Duminica
    AFAIK there is no support, and I have no idea how compatible FPC will be for generics and other language aspects.
    At this point, FPC compatibility will have to be handled by someone else (since I’m not using FPC).

Comments are closed.