Dynamic array + constant array = incompatible

Dynamic array + constant array = incompatible

I still think this is retarded, particularly with the new array syntax.

function Check(const Extras: array of String): Boolean;
var
  List: Array of String;
begin
  FillWithDefaults(List);
  List := List + Extras;  //<--  [dcc32 Error]: E2008 Incompatible types

Comments

  1. Reading that, my reaction is surely that should work with the new array syntax (as you say.) Isn't this exactly the sort of thing it's meant for?

    Maybe file a QC report.

    ReplyDelete
  2. That does seem odd. A quick experiment, however, shows that if you declare:

    type
      TStrArray = array of string;

    var
      MyStrArray: TStrArray;

    and this method:

    procedure TForm1.AddStrings(const strings: TStrArray);
    begin
      MyStrArray := MyStrArray + strings;
    end;

    It builds.

    ReplyDelete
  3. A cent for every time a Delphi developer gets that wrong... (and I admit, its confusing because of the ambiguous syntax)

    const array of X as argument type of a routine -> open array
    array of X on a variable -> dynamic array

    open array incompatible with dynamic array

    So:

    function Check(const Extras: TArray): Boolean;
    var
      List: TArray;
    begin
      FillWithDefaults(List);
      List := List + Extras;
      ...

    ReplyDelete
  4. I think the issue comes from the fact there are two different ways to interpret that code, the classic being an open array parameter, which is NOT compatible with a dynamic array.
    Haven't tried, but that's my impression at first sight.

    ReplyDelete
  5. Shouldn't the new array syntax understand it anyway? Even if they're different types of arrays, the coder wants to concatenate them. Since the result is a dynamic array that should be doable...?

    ReplyDelete
  6. David Millington While it would be nice there was never mentioned compatibility of an open array and a dynamic array being part of the new array syntax.

    ReplyDelete
  7. Stefan Glienke Of course, that requires passing a TArray<>, which you might not have (could be a constant for example).

    ReplyDelete
  8. Asbjørn Heid True that. Then you write this:

    uses
      Spring.Collections;

    function Check(const Extras: array of string): Boolean;
    var
      List: TArray;
    begin
      FillWithDefaults(List);
      List := List + TArray.Copy(Extras);
      ...

    However it could be solved by intrinsic compiler support because in this case you first copy the open array to a dynamic array which then gets passed to the concat function to then be thrown away again. Or until that happens you write your own Concat routine that can do that :)

    ReplyDelete
  9. IMO, they should have managed to hide the incompatibility in the new syntax.  Element by element, they are compatible, so there should have been compiler magic to take care of it.

    ReplyDelete
  10. That might be right but that would also mean that an open array should be assignment compatible to a dynamic array. Otherwise it would be inconsistent if it only worked for concat.

    And then we can ask the question if it should be copied? Because the original source of the open array can be a dynamic array, a const array or a slice of those.
    And what if the original source of the open array was a dynamic array (which just gets passed along with the additional hidden length parameter) should it be copied aswell? But that is inconsistent to how dynamic arrays normally behave for assignments. And with all these things in mind think about Delphi being a strictly typed language that permits many assignments that might be compatible binary wise. You would suddenly implement type assignment compatibility for types that are normally not.

    What I would like to see now that we even call the language Object(!!!) Pascal is making TArray a first class citizen of the language with operator overloading and methods like Add, Insert, Delete, IndexOf and so on.

    Yes you can fake this right now by making a record wrapping a TArray but then you lose the direct and fast access on the items.

    ReplyDelete
  11. IMO, a copy would be natural - as it is for a string.

    ReplyDelete
  12. While I agree that assignment should be explicit (localCopy := Copy(paramArray); for example), the Add operator for TArray should work as if the declaration was
      class operator Add(const A: TArray; const B: array of T): TArray;

    At least I can't see any of the ambiguities that exist when you do a straight assignment.

    ReplyDelete

Post a Comment