Recent

Author Topic: TCollection wiki entry  (Read 1196 times)

Thaddy

  • Hero Member
  • *****
  • Posts: 19387
  • Glad to be alive.
Re: TCollection wiki entry
« Reply #15 on: July 08, 2026, 07:08:21 am »
@paweld

No, the previous version was not a generic class but a hybrid: it forced you to derive from TCollectionItem in a non-generic way after all, nothing generic about that.
Since that is a design mistake regarding generics it had to be replaced. You could have derived the rest too in the classical sense. I was definitely not the only one who regarded it as out of place (being very mild here, I leave the explicits out)
The new generic collection resolves any type to a collection. No need to derive an Item class and that was the biggest mistake: you could not use existing structures for example.. >:(

Note In trunk it is even possible to hide the value parameter entirely by using a reference to function:T and use the underlying invoke from that reference (I demo'd that before). I may add that, but the current one compiles in 3.2.2 too.
I can't believe you do not agree, I think of you much higher.

Consider the reworked Book/People example to see why the old version was very, very wrong: it was working code but not generic in all but name since the items were derived classes from TCollectionItem.
« Last Edit: July 08, 2026, 07:54:24 am by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

paweld

  • Hero Member
  • *****
  • Posts: 1670
Re: TCollection wiki entry
« Reply #16 on: July 08, 2026, 07:44:58 am »
Quote from: Thaddy
The new generic collection resolves any type to a collection. No need to derive an Item class and that was the biggest mistake: you could not use existing structures for example.. >:(
And that’s exactly the kind of explanation that’s missing there. If I’m creating new structures and using collections, then using records seems pointless to me; plus, it makes the code harder to read (in my opinion).
But in a case like the one you describe, when you want to adapt existing structures to collections, it’s actually a very good solution.

Quote from: Thaddy
Consider the reworked Book/People example to see why the old version was very, very wrong: it was working code but not generic in all but name.
In that case, TCollection was definitely a generic type - it was just that the elements of that collection were not.
« Last Edit: July 08, 2026, 07:50:49 am by paweld »
Best regards / Pozdrawiam
paweld

Thaddy

  • Hero Member
  • *****
  • Posts: 19387
  • Glad to be alive.
Re: TCollection wiki entry
« Reply #17 on: July 08, 2026, 07:57:53 am »
In that case, TCollection was definitely a generic type - it was just that the elements of that collection were not.
No: TCollectionItem is part of the TCollection paradigm. If you need to derive from that, you can also derive from TCollection itself. And that is not even necessary, because TCollection itself happily accepts a derived TCollectionItem in its constructor. See below for proof.
Definitely not generic and bad design. It confuses classical design with generics.
If you feel more comfortable with that, then do it properly. We all did before generics.
Also do not confuse the purpose of the examples with the possibility to use any type in the new version. The use of records is just such a case.

But I am happy that you at least partially agree.
Code: Pascal  [Select][+][-]
  1. // the olden way
  2. {$mode delphi}
  3. uses classes;
  4. type
  5.   TMyItem = class(TCollectionItem)
  6.   private
  7.     FField:string;
  8.   published
  9.     property Field:string read FField write FField;
  10.   end;
  11.  
  12. var
  13.   Collection:TCollection;
  14.   Item:TMyItem;
  15. begin
  16.   Collection := TCollection.Create(TMyItem);// pass the TCollectionItemClass
  17.   Item := Collection.Add as TMyItem;
  18.   Item.Field := 'Test';
  19.   Item := Collection.Items[0] as TMyItem;
  20.   writeln(Item.Field);  
  21.   Collection.free;  
  22. end.
So, given that, what is the purpose of that old code? There is none.
If you derive from TCollectionItem anyway you don't need generics at all.
That old code was bad for that reason..
« Last Edit: July 08, 2026, 10:09:04 am by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12513
  • Debugger - SynEdit - and more
    • wiki
Re: TCollection wiki entry
« Reply #18 on: July 08, 2026, 08:52:30 am »
IMHO, an introduction into collection should start with little overhead. (and it should be mode objfpc )

That is, generics should be a 2nd step only. Generics - in a way - just hide the concept of creating your own derived item class.

Even if in the end it would turn out that no one does it by hand, it should be explained. There must be an example that shows how to derive your own item. The classic way.

Only after that, should there be a generic example (and in mode objfpc.

paweld

  • Hero Member
  • *****
  • Posts: 1670
Re: TCollection wiki entry
« Reply #19 on: July 08, 2026, 08:53:16 am »
Quote from: Thaddy
So, given that, what is the purpose of that old code?
Quote from: 007 (from Lazarus Wiki)
Save time overriding the same methods each time you want to create a collection quickly. It does it for you.

I only use Collections when I need to store data in JSON format, because then I can (de)serialize it with a simple piece of code - and I just checked your implementation, and unfortunately that’s no longer possible because the “Value” property cannot be published.

Otherwise, I use lists (maps) from the fgl module.
« Last Edit: July 08, 2026, 08:54:56 am by paweld »
Best regards / Pozdrawiam
paweld

Thaddy

  • Hero Member
  • *****
  • Posts: 19387
  • Glad to be alive.
Re: TCollection wiki entry
« Reply #20 on: July 08, 2026, 09:11:29 am »
IMHO, an introduction into collection should start with little overhead. (and it should be mode objfpc )
Unless I misread: that is already covered in the non-generic part of the wiki entry, which I left intact, but otherwise I will add my little example above.
I only changed the generics part because that was nonsensical and that little example above is proof of that..
About mode: I strongly disagree. Like many I need my code to compile in Delphi too. And the generics syntax for mode objfpc is to some extend legacy because it came from before Delphi supported generics in a - much - cleaner way. (I am aware of some more flexibilities, though) But I can rework or add an example in mode objfpc if you insist. I am not going to change the unit, though, only bug fixes or enhancements.
I can add something like this:
Code: Pascal  [Select][+][-]
  1. program simpledemo;
  2. {$ifdef fpc}{$mode objfpc}{$endif}
  3. uses
  4.   Classes, GenCollection;
  5. type
  6.   // define a custom collection item and a custom collection
  7.   TStringItem = specialize TGenericCollectionItem<string>;
  8.   TStringCollection = specialize TGenericCollection<string>;
  9. var
  10.   StringCollection: TStringCollection;
  11.   Item:TStringItem ;
  12. begin
  13.   StringCollection := TStringCollection.Create;
  14.   try
  15.     StringCollection.Add.Value := 'First Item';
  16.     StringCollection.Add.Value := 'Second Item';
  17.     for Item in StringCollection do  // automatic support for for in do
  18.       with Item do writeln(Value:10,Id:4);
  19.   finally
  20.     StringCollection.Free;
  21.   end;
  22.   readln;
  23. end.
I only changed the mode and added two specialize and now it does not compile in Delphi  :D :D :D
I guess that is what you want?  O:-) O:-)

This whole exercise is about improving the wiki and the theory behind generics, nothing more, nothing less.
If you think it is warranted, I can do a full rewrite of the non-generic part too, but as was already mentioned by someone else in this thread, that is probably not the case.
Although I might lift, rework and move the notifications example, because that is not related to generics?
« Last Edit: July 08, 2026, 09:46:39 am by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12513
  • Debugger - SynEdit - and more
    • wiki
Re: TCollection wiki entry
« Reply #21 on: July 08, 2026, 09:59:53 am »
About the mode Delphi vs Objfpc.

The question is, if the Wiki should be seen as a learning resource, or a means to share code snippets (to be used never mind if understood or not).

IMHO the use of the "specialize" keyword adds clarity for the novice reader. The short Delphi form (just <> ) requires that the reader is familiar with this, and pays attention to those little details.

IMHO the code should aim at learners, and should provide clarity for them first. If on top of that re-usable code snippets should be added, then ok. (IMHO, anyone can quickly adapt them for their needs).




Also, this Wiki is for FPC, not for the Delphi compiler. So from that point it also makes sense to chose the FPC mode. "Mode Delphi" is for emulating a different compiler.



Both points just my opinion (as user) on the issue. No more.

Thaddy

  • Hero Member
  • *****
  • Posts: 19387
  • Glad to be alive.
Re: TCollection wiki entry
« Reply #22 on: July 08, 2026, 10:10:47 am »
Otherwise, I use lists (maps) from the fgl module.
See the remarks section: I do that too.
objects are fine constructs. You can even initialize them with constructors.

Thaddy

  • Hero Member
  • *****
  • Posts: 19387
  • Glad to be alive.
Re: TCollection wiki entry
« Reply #23 on: July 08, 2026, 10:14:36 am »
IMHO the code should aim at learners, and should provide clarity for them first. If on top of that re-usable code snippets should be added, then ok. (IMHO, anyone can quickly adapt them for their needs).
I agree: the wiki is a learning resource. I will add that objfpc mode example, but I am not going to change the unit: that should be opaque anyway. I will also lift the notifications example and put it above the generics part. That was a mistake by me to put that feature in the context of generics, which it isn't.
« Last Edit: July 08, 2026, 10:17:10 am by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

Thaddy

  • Hero Member
  • *****
  • Posts: 19387
  • Glad to be alive.
Re: TCollection wiki entry
« Reply #24 on: July 08, 2026, 10:51:28 am »
Martin, please comment on this. Is OK?
https://wiki.freepascal.org/TCollection#Basics explains the real basics
https://wiki.freepascal.org/TCollection#Notifications explains observer pattern
« Last Edit: July 08, 2026, 11:26:34 am by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

korba812

  • Sr. Member
  • ****
  • Posts: 485
Re: TCollection wiki entry
« Reply #25 on: July 08, 2026, 12:04:21 pm »
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.

Thaddy

  • Hero Member
  • *****
  • Posts: 19387
  • Glad to be alive.
Re: TCollection wiki entry
« Reply #26 on: July 08, 2026, 12:33:24 pm »
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.
- The number of fields is an extremely silly remark...Don't make me call you stupid. You are a decent programmer. The generic version support any type whatever the size.

- 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 partially working for trunk 3.3.1
This is similar to the TRTTIxxx components anyway. It already exists....
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 and some low level implementation difference.
Records are - for now - streamed as Binary properties and there is currently a limitation on managed type fields (pointers), but those can be also streamed as subproperties eventually. (You may want to examine the RTTI unit in trunk)

« Last Edit: July 08, 2026, 01:23:41 pm by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12513
  • Debugger - SynEdit - and more
    • wiki
Re: TCollection wiki entry
« Reply #27 on: July 08, 2026, 12:49:31 pm »
I haven't checked what is old/new... (so some comments might not be on your changes)

But in "constructor THairItem.Create" I wonder about the <> nil check... A collection item can be created with nil, and later added.

It wouldn't necessary be a simple example anymore if it was called with nil, but the check isn't simple either. At best an "assert" or "if raise"?

Not tested, but observer shouldn't need the "as"
" Collection.FPOAttachObserver(Observer as TCollectionObserver);"



Generics.  I find it impossible to read without "generic" / "specialize" keyword. This is the FPC compiler. Mode Delphi is a simulation of a different compiler...
Yes, you have it in the example. But the unit itself is for the Delphi wiki, not for the FPC wiki. (I wont object, but I will state I find it terrible)


But (while it would not necessarily be beginner friendly) all 3 specialization could afaik be done at once / need to verify. The generic and enumerator could be "public type" in the specialized collection?


Thaddy

  • Hero Member
  • *****
  • Posts: 19387
  • Glad to be alive.
Re: TCollection wiki entry
« Reply #28 on: July 08, 2026, 12:50:39 pm »
THairItem is not my work. I left that with respect to and for the original author and it is proper code.
I left everything from "Simple example" upto but not including "Notifications" as is.

And yeah, probably the as is superfluous.
Then again: when working with the simple, non-generic, non-derived TCollection, you need as (or hardcasts, which is even worse) because it relies on runtime verification of the item type.  That is the model that is used for the original TCollection when used in its simplest way. ( don't ask me why: It works like that since Delphi 1) And frankly, that is not bad at all given the language limitations at the time.

I still disagree with you about the mode and my motivation is very strong. InterOp is important. The same feature is also missing in Delphi.
But I can add a unit that is fully mode objfpc of course ...   :P I am proficient in both modes. It is a two minute "fix".
« Last Edit: July 08, 2026, 01:35:12 pm by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12513
  • Debugger - SynEdit - and more
    • wiki
Re: TCollection wiki entry
« Reply #29 on: July 08, 2026, 02:36:10 pm »
I still disagree with you about the mode and my motivation is very strong. InterOp is important.

As I said, I wont object. If the wiki had some TPageControl like tabs, I'd say do both, but....

"InterOp" in general yes, ... But imho this is about TCollection and that is the stronger point. And, the interop is limited either way. Unless you dedicate a new unit for that code. Given the size of it, I would expect most to copy it (if they use it "as is") into an existing unit. And that will have either one mode, and only that one mode will work, the other wont. So just because FPC can mode Delphi, does in no way mean that mode Delphi code is more interop than mode objfpc code.  (in the context of wiki examples / not in the context of fully packed packages, where the content of files isn't touched)

My 2 cents.

Anyway, you do/didthe work, I am fine if you make the call.

 

TinyPortal © 2005-2018