Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2021-02

Generic routines for both dynamic array and other collections

13 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Виктор Матузенко

Hi,

I am trying to write some generic routines for working with containers. For example, GetLength function:

unit u;
{$MODE FPC}
{$MODESWITCH DEFAULTPARAMETERS}
{$MODESWITCH OUT}
{$MODESWITCH RESULT}
interface
generic function GetLength<TContainter>(const V: TContainter): SizeUInt;
implementation
generic function GetLength<TContainter>(const V: TContainter): SizeUInt;
begin
  Exit(V.Count);
end;
end.
// the program
{$MODE FPC}
{$MODESWITCH DEFAULTPARAMETERS}
{$MODESWITCH OUT}
{$MODESWITCH RESULT}
{$MODESWITCH TYPEHELPERS}
uses
  u;
type
  TDynArray = array of PtrInt;
TDynArrayHelper = type helper for TDynArray
  function Count: SizeUInt;
end;
function TDynArrayHelper.Count: SizeUInt;
begin
  Exit(System.Length(Self));
end;
var
  V: TDynArray;
begin
  v := [0,  1,  2,  3,  5,  6,  7, 10, 11, 12,  13,  15,  16];
  Writeln(specialize GetLength<TDynArray>(v));
end.
It gives the following compilation error:
u.pas(16,10) Error: Illegal qualifier

Is the problem because the helper is not known while compiling the unit?

How do I write a generic routine GetLength which will work both for dynamic arrays and for records, objects, classes with Count property?

Victor Matuzenko (Виктор Матузенко)

Reply by email

Ryan Joseph
to Виктор Матузенко
Show quoted text 27 lines
On Feb 20, 2021, at 5:19 AM, Виктор Матузенко via fpc-pascal wrote: Hi, I am trying to write some generic routines for working with containers. For example, GetLength function: unit u; {$MODE FPC} {$MODESWITCH DEFAULTPARAMETERS} {$MODESWITCH OUT} {$MODESWITCH RESULT} interface generic function GetLength<TContainter>(const V: TContainter): SizeUInt; implementation generic function GetLength<TContainter>(const V: TContainter): SizeUInt; begin Exit(V.Count); end; end.

The helper needs to be in the unit file so that GetLength() knows about Count().

Regards,
Ryan Joseph

Reply by email

Виктор Матузенко
to Ryan Joseph

And how do I write generic helper for all possible dynamic arrays?

вс, 21 февр. 2021 г. в 00:57, Ryan Joseph via fpc-pascal <

Show quoted text 18 lines
: > On Feb 20, 2021, at 5:19 AM, Виктор Матузенко via fpc-pascal < > wrote: > The helper needs to be in the unit file so that GetLength() knows about Count(). Regards, Ryan Joseph _______________________________________________ fpc-pascal maillist - https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Victor Matuzenko (Виктор Матузенко)

Reply by email

Ryan Joseph
to Виктор Матузенко
On Feb 20, 2021, at 7:52 PM, Виктор Матузенко via fpc-pascal wrote: And how do I write generic helper for all possible dynamic arrays?

By hand sadly. The RTL has added type helpers for many types but I don't think they added these for dynamic arrays. I agree that dynamic arrays should have a "Count" method by default and the RTL should provide "array of T" for all intrinsic types.

Regards,
Ryan Joseph

Reply by email

Sven Barth
to Ryan Joseph
Ryan Joseph wrote 5 lines
> On Feb 20, 2021, at 7:52 PM, Виктор Матузенко via fpc-pascal wrote: > > And how do I write generic helper for all possible dynamic arrays? By hand sadly. The RTL has added type helpers for many types but I don't think they added these for dynamic arrays. I agree that dynamic arrays should have a "Count" method by default and the RTL should provide "array of T" for all intrinsic types.

You are supposed to use Length(X). There is no need for a "property". One doesn't need to objectify each and everything!

Regards,
Sven

Reply by email

James Richters
to Sven Barth

I've been using a lot of dynamic arrays of records lately, Some are even Dynamic Arrays of records that contain other records, for example: Type
XYZ_Record = Record
X,Y,Z : Double

   End;
   Call_Stack_Record = Record
      Location : LongInt;
      Offset   : XYZ_Record;
      Rotation : Double;
   End;
   Call_Stack : Array of Call_Stack_Record;
Then I do things like:
Call_Stack[I].Offset.X := 12.345

Making a helper to handle "All Possible Dynamic Arrays" would have to handle this kind of dynamic array of record structure... then the helper would just end up being way more complicated than just using the dynamic array, because you can't know every kind of array that might be defined. I honestly don't see what you need a helper for dynamic arrays in the first place. They are pretty straight forward.

I initialize (or reset) the array with
SetLength(X,0);
Then add things to it with:
SetLength(X,Length(X)+1);
X[Length(X)] := Data;
Remove things from it with
SetLength(X,Length(X)-1);
Search through it with
For I = 0 to Length(X)-1 Do
   Begin
      If X[I] = Test Then
         Do_Something;
   End;

Etc...

I had some count variables to keep track of how many elements were in the Arrays, but I got rid of them all because Length() is already there so I didn't see any reason to clutter up my code with another variable to keep track of... Length() ALWAYS reports an accurate count of the array elements... having a separate count variable could go wrong and be off from the actual number of elements.

James

Earlier message 19 lines
-----Original Message----- From: fpc-pascal On Behalf Of Sven Barth via fpc-pascal Sent: Sunday, February 21, 2021 5:00 PM To: FPC-Pascal users discussions Cc: Sven Barth ; Ryan Joseph Subject: Re: [fpc-pascal] Generic routines for both dynamic array and other collections Am 21.02.2021 um 15:59 schrieb Ryan Joseph via fpc-pascal: > >> On Feb 20, 2021, at 7:52 PM, Виктор Матузенко via fpc-pascal wrote: >> >> And how do I write generic helper for all possible dynamic arrays? > By hand sadly. The RTL has added type helpers for many types but I don't think they added these for dynamic arrays. I agree that dynamic arrays should have a "Count" method by default and the RTL should provide "array of T" for all intrinsic types. You are supposed to use Length(X). There is no need for a "property". One doesn't need to objectify each and everything! Regards, Sven

Reply by email

Sven Barth
to James Richters: I've been using a lot of dynamic arrays of records lately, Some are even Dynamic Arrays…

James Richters schrieb am Mo.,
22. Feb. 2021, 01:07:

Show quoted text 21 lines
I've been using a lot of dynamic arrays of records lately, Some are even Dynamic Arrays of records that contain other records, for example: Type XYZ_Record = Record X,Y,Z : Double End; Call_Stack_Record = Record Location : LongInt; Offset : XYZ_Record; Rotation : Double; End; Call_Stack : Array of Call_Stack_Record; Then I do things like: Call_Stack[I].Offset.X := 12.345 Making a helper to handle "All Possible Dynamic Arrays" would have to handle this kind of dynamic array of record structure...

No. Assuming generic helpers would be supported it would be something like(!) this:

=== code begin ===

type
  generic TArrayHelper<T> = type helper for array of T
  private
    function GetCount: SizeInt; inline;
  public
    property Count: SizeInt read GetCount;
  end;
function TArrayHelper.GetCount: SizeInt;
begin
  Result := Length(Self);
end;
type
  TLongintArrayHelper = specialize TArrayHelper<LongInt>;
var
  arr: array of LongInt;
begin
  SetLength(arr, 5);
  Writeln(arr.Count);
end.

=== code end ===

In fact this is already possible for named array types.

No special handling for your situation needed. And the generated code itself would be similar as well due to the inline.

Doesn't change my opinion though that we don't *need* this.

Regards,
Sven

Reply by email

Sven Barth
to Ryan Joseph: Yes but programmers tend to be neurotic and obsessive. :) I think many of us would…

Ryan Joseph via fpc-pascal schrieb am
Mo., 22. Feb. 2021, 13:07:

Show quoted text 12 lines
> On Feb 21, 2021, at 2:59 PM, Sven Barth wrote: > > You are supposed to use Length(X). There is no need for a "property". One doesn't need to objectify each and everything! Yes but programmers tend to be neurotic and obsessive. :) I think many of us would appreciate a matching "Count" method that is consistent with TList<T>.

There's a saying here in Germany:

"Das Leben ist kein Wunschkonzert"

"Life is not a concert of wishes"

I think that applies rather nicely here as well. Arrays are simply no structured types, thus them having "properties" is wrong as well. If users want expect arrays to be object oriented they should use corresponding languages like Java or C#.

Regards,
Sven

Reply by email

Graeme Geldenhuys
to Sven Barth
Sven Barth wrote
If users want expect arrays to be object oriented they should use corresponding languages like Java or C#.

Fully agree. Even Java doesn't "objectify" arrays as some type of object. Hence Java includes the Arrays class that has a static method Arrays.asList() which returns a List<T> container. So yes you can quickly get a container, but arrays are still just arrays. ;-)

Regards,
Graeme

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp

Reply by email

Виктор Матузенко
to Sven Barth: Ryan Joseph via fpc-pascal schrieb am Mo., 22. Feb. 2021, 13:07: There's a saying here…

пн, 22 февр. 2021 г. в 16:11, Sven Barth via fpc-pascal <

Show quoted text 5 lines
: Arrays are simply no structured types,

Actually they are...

thus them having "properties" is wrong as well. If users want expect arrays to be object oriented they should use corresponding languages like Java or C#.

I don't want them to be objects, I want to write some functions once and be able to specialize them
for many different types. I thought this is exactly the purpose of the generic routines feature.

Example of such an algorithm is binary search. I am able to access elements with [] operator of both
arrays and objects, but I cannot get length in a generic way.

Victor Matuzenko (Виктор Матузенко)

Reply by email

Ryan Joseph
to Виктор Матузенко
Show quoted text 5 lines
On Feb 22, 2021, at 4:21 PM, Виктор Матузенко via fpc-pascal wrote: Example of such an algorithm is binary search. I am able to access elements with [] operator of both arrays and objects, but I cannot get length in a generic way.

Length(T) is what you want right?

Regards,
Ryan Joseph

Reply by email

Виктор Матузенко
to Ryan Joseph

вт, 23 февр. 2021 г. в 23:45, Ryan Joseph via fpc-pascal <

Show quoted text 5 lines
: Length(T) is what you want right?

Generic Length(T), yes.

Victor Matuzenko (Виктор Матузенко)

Reply by email