Recent

Author Topic: TCollection wiki entry  (Read 1772 times)

Thaddy

  • Hero Member
  • *****
  • Posts: 19432
  • Glad to be alive.
Re: TCollection wiki entry
« Reply #30 on: July 08, 2026, 03:25:38 pm »
Anyway, you do/didthe work, I am fine if you make the call.
To me it is important that the basics - the non-generic one at the top-  example gets your blessing. You were right that there was an omission for the really basic use, I overlooked that. I hope my contribution solved that.
Point is, there is nothing mysterious about TCollection and when used within proper context it is a valuable asset in its own right.
(I rewrote the generics part only because it was plain wrong.)
https://wiki.freepascal.org/index.php?title=TCollection#Basics for review.
« Last Edit: July 08, 2026, 03:37:10 pm by Thaddy »
Any "programmer" that knows only one programming language is not a programmer

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12537
  • Debugger - SynEdit - and more
    • wiki
Re: TCollection wiki entry
« Reply #31 on: July 08, 2026, 04:12:04 pm »
I may have another look at the weekend...

Thaddy

  • Hero Member
  • *****
  • Posts: 19432
  • Glad to be alive.
Re: TCollection wiki entry
« Reply #32 on: July 08, 2026, 09:49:51 pm »
I think I am almost there: shoot holes in it!! (not silly comments about element sizes or records, plz, THINK!, that was really silly and not helpful at all)
https://wiki.freepascal.org/index.php?title=TCollection
Simple example and streaming stays the original entry. (Although it contains a reference to third party code written by our member AVK who is by now a much better programmer than I ever need to be)

All other things touched by me. I hope for the better.
- tell me if something is wrong, no opinions, facts.
- tell me if something is not clear.
- tell me to better formulate.

To me it is crucial that the wiki entries are correct. There is a lot more to repair, so I ask advice on this forum before making radical changes like this one.
« Last Edit: July 08, 2026, 10:44:41 pm by Thaddy »
Any "programmer" that knows only one programming language is not a programmer

Thaddy

  • Hero Member
  • *****
  • Posts: 19432
  • Glad to be alive.
Re: TCollection wiki entry
« Reply #33 on: July 09, 2026, 04:59:49 pm »
Added enumerator use. https://wiki.freepascal.org/index.php?title=TCollection#Enumerators
Also added a dedicated unit for external enumerators for TCollections.
https://wiki.freepascal.org/TCollection#external_generic_enumerators_unit
Defined are:
- reversed traversal pattern (a.k.a. LIFO traversal)
- stepwise traversal pattern (a.k.a. skipping traversal)
- windowed traversal pattern (a.k.a partial traversal)
These are the most common patterns for which external generic enumerators make sense.
« Last Edit: July 10, 2026, 04:12:53 pm by Thaddy »
Any "programmer" that knows only one programming language is not a programmer

Thaddy

  • Hero Member
  • *****
  • Posts: 19432
  • Glad to be alive.
Re: TCollection wiki entry
« Reply #34 on: July 10, 2026, 04:22:36 pm »
Can I rewrite the hair part and streaming part too (using the original code, but made into working, compiling examples)?
Topics:
https://wiki.freepascal.org/TCollection#Simple_example
https://wiki.freepascal.org/TCollection#Streaming

Which are not written by me and have no compilable examples. Code is fine, though.

Btw: if someone has other useful patterns for the generic enumerators unit I can add them.
« Last Edit: July 10, 2026, 04:28:43 pm by Thaddy »
Any "programmer" that knows only one programming language is not a programmer

mas steindorff

  • Hero Member
  • *****
  • Posts: 603
Re: TCollection wiki entry
« Reply #35 on: July 10, 2026, 08:08:14 pm »
I think this wiki page is getting a bit long, maybe break out the bulk of the generics version to a new page?  I think smaller pages in general are easier to maintain.

I did find and add a link on the bottom to a general containers page that can be use to tie some of these pages together.
https://wiki.freepascal.org/Data_Structures,_Containers,_Collections

I'm not sure what the 3rd party stuff is on this summery page are or if it's still relevant with the latest FPC. this would be the place for my comparison table I suggested be added some day.

Mas 
 
windows 10 &11, Ubuntu 21+ IDE 3.4 general releases

Thaddy

  • Hero Member
  • *****
  • Posts: 19432
  • Glad to be alive.
Re: TCollection wiki entry
« Reply #36 on: July 10, 2026, 08:48:54 pm »
I think smaller pages in general are easier to maintain.
I aim for completeness and that means it is indeed became a bit long.
I will see if I can restructure it into two or three separate entries and use cross referral.
I identified already four:
- Collections and Enumerators for collections
- Generic, type safe, collections
- Generic enumerators (can cover TStringlist as well with the same code)
- Observer pattern and its default implementation for TCollection and TStringlist.
I consider rewiting it as such.

OTOH it is very complete and all - correct - info in one spot is also an asset.
Any "programmer" that knows only one programming language is not a programmer

korba812

  • Sr. Member
  • ****
  • Posts: 486
Re: TCollection wiki entry
« Reply #37 on: July 11, 2026, 12:20:33 am »
Your solution doesn't seem very practical in the real world:
- A collection element rarely has just one field.
- The example with a record as a field isn't streamable.
Yes it is: I am writing a generic serializer unit that streams all published properties as long as they have sufficient RTTI.
This is probably not possible for 3.2.2, but is already working for trunk 3.3.1
A record declared in {$M+} state has sufficient (extended) RTTI. The serializer already works in Delphi but not quite stable in FPC due to some issue with getproperties.

The number of fields is a extremely silly remark...Don't make me call you stupid.
Maybe I'm stupid, but I don't see any benefit to a generic collection item.

Thaddy

  • Hero Member
  • *****
  • Posts: 19432
  • Glad to be alive.
Re: TCollection wiki entry
« Reply #38 on: July 11, 2026, 07:06:53 am »
Maybe I'm stupid, but I don't see any benefit to a generic collection item.
There are some important ones:
- streaming
- notifications
- it has both an index in the collection and a unique ID, index can change, but the ID can not.
- for items specific: type safety of course, without casts.
Otherwise it behaves much like a TList<T>, or TfpList, which is the underlying structure anyway. (I wrote that in the remarks)
It has otherwise different, some say better, semantics than a list.
It is a bit an underrated structure because people found it difficult or cumbersome to use. (It isn't)
But if a TList<T> satisfies your use case, use that. For strings, the standard TStringlist is similar. and also has notifications.
A collection behaves more like a database table than a list. For which it was designed, it is a lightweight database system: You can connect items from different collections over their persisted ID, something you can not do without extra work with a TList<T> and you can stream to and from file.
« Last Edit: July 11, 2026, 07:26:28 am by Thaddy »
Any "programmer" that knows only one programming language is not a programmer

korba812

  • Sr. Member
  • ****
  • Posts: 486
Re: TCollection wiki entry
« Reply #39 on: July 11, 2026, 08:18:03 pm »
You've described the features and advantages of collections. However, that doesn't explain the rationale behind a generic collection item. TCollection is a collection of TCollectionItem objects, not a generic container. But a generic collection and enumerator could make sense. In my humble opinion, it could look something like this (sometime in the future):
Code: Pascal  [Select][+][-]
  1. program project1;
  2.  
  3. {$mode objfpc}
  4.  
  5. uses
  6.   Classes, SysUtils;
  7.  
  8. type
  9.   generic TGenericCollectionEnumerator<T: TCollectionItem> = class(TCollectionEnumerator)
  10.   public
  11.     function GetCurrent: T;
  12.     property Current: T read GetCurrent;
  13.   end;
  14.  
  15.   generic TGenericDerivedCollection<T: TCollectionItem; TC: TCollection> = class(TC)
  16.   protected
  17.     procedure SetItem(Index: integer; AValue: T);
  18.     function GetItem(Index: Integer): T;
  19.   public
  20.     function Add: T;
  21.     function GetEnumerator: specialize TGenericCollectionEnumerator<T>;
  22.     property Items[Index:integer]:T read GetItem write SetItem; default;
  23.   end;
  24.  
  25.   generic TGenericCollection<T: TCollectionItem> = class(specialize TGenericDerivedCollection<T, TCollection>);
  26.  
  27.   // Test classes
  28.  
  29.   TMyItem = class(TCollectionItem)
  30.   private
  31.     FAge: Integer;
  32.     procedure SetAge(AValue: Integer);
  33.   published
  34.     property Age: Integer read FAge write SetAge;
  35.   end;
  36.  
  37.   TMyItemEx = class(TMyItem)
  38.   private
  39.     FHeight: Integer;
  40.   published
  41.     property Height: Integer read FHeight write FHeight;
  42.   end;
  43.  
  44.   TMyCollection = specialize TGenericCollection<TMyItem>;
  45.   TMyCollectionEx = specialize TGenericDerivedCollection<TMyItemEx, TMyCollection>;
  46.   TMyOwnedCollection = specialize TGenericDerivedCollection<TMyItem, TOwnedCollection>;
  47.  
  48.   TOtherItem = class(TCollectionItem)
  49.   end;
  50.  
  51.   //Type check
  52.   //TOtherCollection = specialize TGenericDerivedCollection<TOtherItem, TMyCollection>;
  53.  
  54. function TGenericCollectionEnumerator.GetCurrent: T;
  55. begin
  56.   Result := T(inherited GetCurrent);
  57. end;
  58.  
  59. procedure TGenericDerivedCollection.SetItem(Index: integer; AValue: T);
  60. begin
  61.   inherited SetItem(Index, AValue);
  62. end;
  63.  
  64. function TGenericDerivedCollection.GetItem(Index: Integer): T;
  65. begin
  66.   Result := T(inherited GetItem(Index));
  67. end;
  68.  
  69. function TGenericDerivedCollection.Add: T;
  70. begin
  71.   Result := T(inherited Add);
  72. end;
  73.  
  74. function TGenericDerivedCollection.GetEnumerator: specialize
  75.   TGenericCollectionEnumerator<T>;
  76. begin
  77.   // FPC trunk fails with:
  78.   // project1.lpr(87,55) Error: Duplicate identifier "TGENERICCOLLECTIONENUMERATOR$1$crc7ED07D64_crc391C2F9C"
  79.   // Result := specialize TGenericCollectionEnumerator<T>.Create(Self);
  80.   Result := nil; // for now
  81. end;
  82.  
  83. procedure TMyItem.SetAge(AValue: Integer);
  84. begin
  85.   if FAge = AValue then Exit;
  86.   if AValue < 0 then
  87.     raise Exception.Create('Age cannot be negative!');
  88.   FAge := AValue;
  89. end;
  90.  
  91. var
  92.   MyItem: TMyItem;
  93.   MyItemEx: TMyItemEx;
  94.   Items: TMyCollection;
  95.   ItemsEx: TMyCollectionEx;
  96.  
  97. begin
  98.   Items := TMyCollection.Create(TMyItem);
  99.   ItemsEx := TMyCollectionEx.Create(TMyItemEx);
  100.   MyItem := Items.Add;
  101.   MyItem.Age := 18;
  102.   WriteLn(Items[0].Age);
  103.   MyItemEx := ItemsEx.Add;
  104.   MyItemEx.Age := 20;
  105.   MyItemEx.Height := 180;
  106.   //for MyItem in Items do
  107.   //  WriteLn(MyItem.Age);
  108.   //Type check
  109.   //MyItemEx := Items.Add;
  110. end.
  111.  

Thaddy

  • Hero Member
  • *****
  • Posts: 19432
  • Glad to be alive.
Re: TCollection wiki entry
« Reply #40 on: July 12, 2026, 05:44:53 am »
Yes, I could add that, although there is no need to derive from TCollectionEnumerator if you reimplement it anyway, which is what I did. And it avoids any issues with trunk ;)
The only advantage would be that implementing getenumerator is not necessary (if that would work).
External enumerators do not suffer from that because they implement it on self..
Anyway, I will see if I can get your approach working.
Any "programmer" that knows only one programming language is not a programmer

Thaddy

  • Hero Member
  • *****
  • Posts: 19432
  • Glad to be alive.
Re: TCollection wiki entry
« Reply #41 on: July 13, 2026, 01:24:21 pm »
It would be nicer to implement almost everything if only TCollection exposes the list... (readonly)

Anyway: also changed the hair simple and streaming examples that were not written by me, into compilable programs, leaving much of the original code intact, but removed the silly dependency on lresource which is not part of the rtl. (and does not add anything useful for simple streaming).
For simple examples, the only dependency should be classes, nothing else.
« Last Edit: July 13, 2026, 04:08:50 pm by Thaddy »
Any "programmer" that knows only one programming language is not a programmer

DonAlfredo

  • Hero Member
  • *****
  • Posts: 1883
Re: TCollection wiki entry
« Reply #42 on: July 14, 2026, 09:17:43 am »
Quote
A collection behaves more like a database table than a list. For which it was designed, it is a lightweight database system
In that case, it would perhaps also be nice to have an example of an enumerator that selects on a field (contents).
E.g. enumerate over only red hair.

Thaddy

  • Hero Member
  • *****
  • Posts: 19432
  • Glad to be alive.
Re: TCollection wiki entry
« Reply #43 on: July 14, 2026, 09:49:21 am »
In that case, it would perhaps also be nice to have an example of an enumerator that selects on a field (contents).
E.g. enumerate over only red hair.
But enumerator over specific fields is added two times: It is already in the flintstones/doe example.
And is done in the reworked books example: it uses two collections, one for author and books, and one for readers and books, connected over book.id, then outputs who reads which book.
8.2 and 8.3
But I can make non-generic versions for them.
« Last Edit: July 14, 2026, 10:01:50 am by Thaddy »
Any "programmer" that knows only one programming language is not a programmer

DonAlfredo

  • Hero Member
  • *****
  • Posts: 1883
Re: TCollection wiki entry
« Reply #44 on: July 14, 2026, 10:19:03 am »
I meant something like this.
Code: Pascal  [Select][+][-]
  1. Surnames:=Surnames.Create({Surname=}'Flintstone');
  2. for Person in Surnames ...; // enumerate only over all Flintstone persons

 

TinyPortal © 2005-2018