<div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">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 style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "><br></div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">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 style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "><br></div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "><a href="http://wiki.freepascal.org/FPC_New_Features_Trunk" target="_blank" style="color: rgb(119, 153, 187); ">http://wiki.freepascal.org/FPC_New_Features_Trunk</a></div>
<div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "><br></div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">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 style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "><br></div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">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 style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "><br></div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">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 style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "><br></div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">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 style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "><br></div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">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 style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "><br></div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">Jump: So here are some of the problems I've found with fpc generics. </div>
<div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "><br></div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">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 style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "><br></div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">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 style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "><br></div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">type</div>
<div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "> TStringConverter<T> = function(Item: T): string; // okay delphi mode, in objfpc this line should begin with generic</div>
<div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "> </div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "> TMyForm = class(TForm) </div>
<div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "> procedure ShowContents<T>(List: TList<T>; Converter: TStringConverter<T>);</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">
<br></div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">...</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">
<br></div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">// Having a generic method is not okay </div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">
procedure TMyForm.ShowContents<T>(List: TList<T>; Converter: TStringConverter<T>);</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">var</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">
Item: T;</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">begin </div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">
ListBox.Items.BeginUpdate;</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "> try</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">
ListBox.Items.Clear;</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "> for Item in List do</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">
ListBox.Items.Add(Converter(Item));</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "> finally</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">
ListBox.Items.EndUpdate;</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "> end;</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">
end;</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "><br></div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">
You can't use generics without specialization.</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "><br></div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">
// This is not okay. Instead you have to specialize TList<T> and TStringConverter<T> inside TMyTestObject<T></div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">
procedure TMyTestObject<T>.DumpContents(List: TList<T>; Converter: TStringConverter<T>);</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">var</div>
<div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "> Item: T;</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">begin </div>
<div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "> FStrings.BeginUpdate;</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">
try</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "> FStrings.Clear;</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">
for Item in List do</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "> FStrings.Add(Converter(Item));</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">
finally</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "> FStrings.EndUpdate;</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">
end;</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">end;</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">
<br></div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">Specialization leads to problems, as specialized types from one class cannot be share with another class. Also you cannot use specialization inside an interface.</div>
<div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "><br></div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "> IMyInterface<T> = interface</div>
<div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "> function GetCurrent: T;</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">
// because of we specialization can't use other generics in an interface</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "> function CurrentString(Converter: TStringConverter<T>): string;</div>
<div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "> procedure TakeFirst(List: TList<T>);</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">
property Current: T read GetCurrent;</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "> end;</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">
<br></div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">The solution:</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">
<br></div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">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 style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "><br></div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">type TMyClass = class List: TList<Integer>; end;</div>
<div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "><br></div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">or</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">
<br></div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">type TMyClass = class procedure CountDistinct<T>(List: List<T>); end;</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">
<br></div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">or</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "><br>
</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">type TMyClass = class function Combine(List: List<string>): string; end;</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">
<br></div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">or</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "><br>
</div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "><div style="font-size: 13px; ">type TMyInterface<T> = function MyMethod(List: List<T>; Converter: TStringConverter<T>): Integer; end;</div>
<div><br></div></div><div style="font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">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>