<div>Jump to "So here are some of the problems I've found with fpc generics" if you don't want to read the backstory. </div><div><br></div><div>I haven't been active in the FPC for a while, but last week I was asking some questions about the upcoming Delphi FireMonkey project which is supposed to allow broader development with Pascal/Delphi. My first question to a newsgroup was, what about FPC, is the FireMonkey project going to work with it? I was redirected to this article:</div>
<div><br></div><div><a href="http://wiki.freepascal.org/FPC_New_Features_Trunk">http://wiki.freepascal.org/FPC_New_Features_Trunk</a></div><div><br></div><div>Great, these were the new features I was looking for, bridging Delphi and FPC {$mode delphi} features. So then last week I switched my laptop windows SSD for my linux SSD and got the latest sources of FPC and Lazarus sources. I wrote a new XML wrapper around both libxml and msxml, and then dove into converting my Delphi generics library. My eventual goal is to create the best cross platform game engine ever based on Delphi/Pascal.</div>
<div><br></div><div>I filled out a few bugs on the issue tracker for Lazarus where the new generic syntax for {$mode delphi} broke CodeTools. Then sent a few patches to fix those issues myself (yeah me).</div><div><br></div>
<div>But then on Saturday I started out porting my generics library, and quickly began to fall into depression. It seems FPC have a lot of problems with generics. I had to take a break from all my language testing due to all the problems I kept running into which made my head spin after each session of tryng to figure out what the problems are. </div>
<div><br></div><div>On Sunday I sat down again and started hashing out how to get by with FPC generics. In the evening I finally was able to focus in on the core problems with the way generics work in FPC.</div><div><br></div>
<div>I'd like to contribute to fixing these problems, but honestly I have no idea how to modify the compiler. I managed to send some patches off for CodeTools, but believe the compiler is a whole other level that needs gross amounts of fixings when it comes to generics. Something I'm not capable of.</div>
<div><br></div><div>Jump: So here are some of the problems I've found with fpc generics. </div><div><br></div><div>This does not include all the bugs that cause the compiler to act irrational one moment and a different irrational the next moment. This is simply a list of the things FPC generics can't do. I mention these rather than the generic compiler bugs, because IMO if the way generics work aren't changed, it's not even worth fixing the compiler bugs the existing syntax brings.</div>
<div><br></div><div>You can't write a generic method in a non generic class. The syntax 'TMyForm.ShowContents<T>' is invalid is invalid in both objfpc and delphi modes. You are forced to define a generic class if you want to use a generic method.</div>
<div><br></div><div>type</div><div> TStringConverter<T> = function(Item: T): string; // okay delphi mode, in objfpc this line should begin with generic</div><div> </div><div> TMyForm = class(TForm) </div><div>
procedure ShowContents<T>(List: TList<T>; Converter: TStringConverter<T>);</div><div><br></div><div>...</div><div><br></div><div>// Having a generic method is not okay </div><div>procedure TMyForm.ShowContents<T>(List: TList<T>; Converter: TStringConverter<T>);</div>
<div>var</div><div> Item: T;</div><div>begin </div><div> ListBox.Items.BeginUpdate;</div><div> try</div><div> ListBox.Items.Clear;</div><div> for Item in List do</div><div> ListBox.Items.Add(Converter(Item));</div>
<div> finally</div><div> ListBox.Items.EndUpdate;</div><div> end;</div><div>end;</div><div><br></div><div>You can't use generics without specialization.</div><div><br></div><div>// This is not okay. Instead you have to specialize TList<T> and TStringConverter<T> inside TMyTestObject<T></div>
<div>procedure TMyTestObject<T>.DumpContents(List: TList<T>; Converter: TStringConverter<T>);</div><div>var</div><div> Item: T;</div><div>begin </div><div> FStrings.BeginUpdate;</div><div> try</div><div>
FStrings.Clear;</div><div> for Item in List do</div><div> FStrings.Add(Converter(Item));</div><div> finally</div><div> FStrings.EndUpdate;</div><div> end;</div><div>end;</div><div><br></div><div>Specialization leads to problems, as specialized types from one class cannot be share with another class. Also you cannot use specialization nside an interface.</div>
<div><br></div><div> IMyInterface<T> = interface</div><div> function GetCurrent: T;</div><div> // because of we specialization can't use other generics in an interface</div><div> function CurrentString(Converter: TStringConverter<T>): string;</div>
<div> procedure TakeFirst(List: TList<T>);</div><div> property Current: T read GetCurrent;</div><div> end;</div><div><br></div><div>The solution:</div><div><br></div><div>Get rid of the whole specialization concept in fpc. Generics should be able to be declared at any point using the type or a generic parameter. You should be able to simply say things like:</div>
<div><br></div><div>type TMyClass = class List: TList<Integer>; end;</div><div><br></div><div>or</div><div><br></div><div>type TMyClass = class procedure CountDistinct<T>(List: List<T>); end;</div><div><br>
</div><div>or</div><div><br></div><div>type TMyClass = class function Combine(List: List<string>): string; end;</div><div><br></div><div>And if someone ever does intent to fix generics in FPC, there are a whole slew of errors that they already bring into the compiler. I'll make a list of examples of those errors at a later time, but they inner workings of generics should be redone to remove the specialization requirement before those errors are addressed.</div>