Recent

Author Topic: Passing partial arrays to procedures with named dynamic array types  (Read 596 times)

Paradice

  • New Member
  • *
  • Posts: 11
Question - in my understanding, the two procedure declarations for "writevalues" below should be equivalent. However, the one with the parameter value "const source: array of integer" compiles and runs exactly as expected; but the one with "const source: TMyArray" gives "
Error: Illegal expression" at the line near the bottom when I attempt to invoke it with a partial array.

Am I missing something obvious, or are 'named' dynamic array types actually different in some important respect when it comes to passing partial dynamic arrays?


Code: Pascal  [Select][+][-]
  1. program Slicetest;
  2.  
  3. type
  4.    TMyArray = array of integer;
  5.  
  6. var
  7.    ints : TMyArray;
  8.  
  9. //procedure writevalues (const source: TMyArray); // <-- this will not compile
  10. procedure writevalues (const source: array of integer); // <-- this compiles fine
  11. var
  12.  int : integer;
  13. begin
  14.    for int in source do
  15.       write(int,',');
  16.    writeln;
  17. end;
  18.  
  19. begin
  20.    ints := [1,2,3,4,5];
  21.    writevalues(ints);
  22.    writevalues(ints[2..3]);   // <- error here
  23. end.
  24.  

cdbc

  • Hero Member
  • *****
  • Posts: 1746
    • http://www.cdbc.dk
Re: Passing partial arrays to procedures with named dynamic array types
« Reply #1 on: January 11, 2025, 08:52:33 am »
Hi
Have a 'looksee' here.
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE5 -> FPC 3.2.2 -> Lazarus 2.2.6 up until Jan 2024 from then on it's: KDE5/QT5 -> FPC 3.3.1 -> Lazarus 3.0

Paradice

  • New Member
  • *
  • Posts: 11
Re: Passing partial arrays to procedures with named dynamic array types
« Reply #2 on: January 11, 2025, 09:05:32 am »
Thanks - that thread confirms what I found, but it doesn't really say anything about why.

Is there an actual language/semantic reason why a named dynamic array type cannot work with the partial array[x..y] syntax?

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 10647
  • Debugger - SynEdit - and more
    • wiki
Re: Passing partial arrays to procedures with named dynamic array types
« Reply #3 on: January 11, 2025, 09:27:05 am »
https://www.freepascal.org/docs-html/ref/refsu68.html

From the language point of view its a different type: open array vs dynamic array.

Open array is defined to allow what you do, and therefore has an implementation that supports that. (i.e. supports it easily)

Open array is passed in such a way, that you don't need to copy the data to pass an array slice (albeit, if you don't use "const foo: array of" or "var ..." then it may still copy it).
Dynamic array would need to make a copy always. This is due to its need of having a refcount, that can only be applied to it as a whole.

Thaddy

  • Hero Member
  • *****
  • Posts: 16300
  • Censorship about opinions does not belong here.
Re: Passing partial arrays to procedures with named dynamic array types
« Reply #4 on: January 11, 2025, 10:32:51 am »
Furthermore, in your particular case, open array parameters do not need to receive the whole array, but the dynamic array version only accepts a whole array of the correct size, no partial parts.
Be aware that if you pass partial values, the index is different and always starts at zero, it is not the index of the elements you pass: not a[2] index 2, but a[2] index 0.
They are two different beasts with an unfortunate similar syntax. Very confusing for beginners.
If I smell bad code it usually is bad code and that includes my own code.

finchley

  • Newbie
  • Posts: 3
Re: Passing partial arrays to procedures with named dynamic array types
« Reply #5 on: January 11, 2025, 12:24:42 pm »
How about a crappily written type helper?


Code: Pascal  [Select][+][-]
  1. program Slicetest;
  2. {$MODESWITCH TYPEHELPERS}
  3.  
  4. type
  5.    TMyArray = array of integer;
  6.    TSlice   = type helper for TMyArray
  7.      function AsSlice(const TypedSource : TMyArray;
  8.                       IdxStart, IdxStop : integer) : TMyArray;
  9.    end;
  10.  
  11. function TSlice.AsSlice(const TypedSource : TMyArray;
  12.                         IdxStart, IdxStop : integer) : TMyArray;
  13.   var
  14.     i, j     : integer;
  15.     temp : TMyArray;
  16. begin
  17.   j := 0;
  18.   SetLength(temp, (IdxStop - IdxStart) + 1);
  19.   for i := IdxStart to IdxStop do begin
  20.     temp[j] := TypedSource[i];
  21.     j := j + 1;
  22.   end;
  23.  
  24.   Result := temp;
  25. end;
  26.  
  27. procedure WriteTypedValues(const TypedSource : TMyArray); // <-- this compiles fine!
  28.   var
  29.     int : integer;
  30. begin
  31.   for int in TypedSource do
  32.     Write(int, ', ');
  33.   WriteLn();
  34. end;
  35.  
  36. procedure WriteAnonValues(const AnonSource : array of integer); // <-- this compiles fine!
  37.   var
  38.    int : integer;
  39. begin
  40.    for int := 0 to high(AnonSource) - 1 do
  41.       Write(AnonSource[int], ', ');
  42.    Write(AnonSource[high(AnonSource)]);
  43.    WriteLn();
  44. end;
  45.  
  46. var
  47.    typed_ints : TMyArray;
  48.    anon_ints  : array of integer;
  49.  
  50. begin
  51.    typed_ints := [1, 2, 3, 4, 5];
  52.    anon_ints  := [1, 2, 3, 4, 5];
  53.  
  54.    { Typed array of integers }
  55.    WriteAnonValues(typed_ints);
  56.    WriteAnonValues(typed_ints[2..3]);   // <- OK Here.
  57.  
  58.    WriteTypedValues(typed_ints);
  59.    //WriteTypedValues(typed_ints[2..3]);  // <- Illegal Expression!
  60.  
  61.    Write('Using Type Helper: ');
  62.    WriteTypedValues(typed_ints.AsSlice(typed_ints, 2, 3));
  63.  
  64.    { Anonymous array of integers }
  65.    WriteAnonValues(anon_ints);
  66.    WriteAnonValues(anon_ints[2..3]);      // <- OK Here.
  67.  
  68.    WriteTypedValues(anon_ints);
  69.    //WriteTypedValues(anon_ints[2..3]);    // <- Illegal Expression!
  70. end.
  71.  

jamie

  • Hero Member
  • *****
  • Posts: 6776
Re: Passing partial arrays to procedures with named dynamic array types
« Reply #6 on: January 11, 2025, 04:33:29 pm »
of course, this can be done with a little coding using the original program modified.
Code: Pascal  [Select][+][-]
  1. program Slicetest;
  2. type
  3.    TMyArray = array of integer;
  4.  
  5. var
  6.    ints : TMyArray;
  7.  
  8. //procedure writevalues (const source: TMyArray); // <-- this will not compile
  9. procedure writevalues (const source:TmyArray;alow:integer=0;ahi:integer=-1);
  10. var
  11.  int : integer;
  12.  theArr:TmyArray;
  13.  CC:integer = -1;
  14. begin
  15.    If (alow >= Length(Source))or((ahi<>-1)and(ahi>Length(Source))) Then
  16.     Begin
  17.       WriteLn(' Range error');
  18.       Readln;
  19.       exit;
  20.     End;
  21. If ahi = -1 Then ahi := length(source);
  22. theArr := Copy(source,alow,ahi);
  23.    for int in theArr do
  24.       Begin
  25.          if CC<>-1 Then write(',');
  26.          write(int); inc(cc);
  27.       end;
  28.    writeln;
  29. end;
  30.  
  31. begin
  32.    ints := [1,2,3,4,5];
  33.    writevalues(ints);
  34.    writevalues(ints,2,3);   // less coding this way.
  35.    Readln;
  36. end.
  37.  
  38.  
jamie
The only true wisdom is knowing you know nothing

 

TinyPortal © 2005-2018