[Lazarus] Generics in FPC have many problems

Anthony Walter sysrpl at gmail.com
Mon Aug 29 15:46:45 CEST 2011


Jump to "So here are some of the problems I've found with fpc generics" if
you don't want to read the backstory.

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:

http://wiki.freepascal.org/FPC_New_Features_Trunk

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.

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).

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.

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.

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.

Jump: So here are some of the problems I've found with fpc generics.

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.

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.

type
  TStringConverter<T> = function(Item: T): string; // okay delphi mode, in
objfpc this line should begin with generic

  TMyForm = class(TForm)
    procedure ShowContents<T>(List: TList<T>; Converter:
TStringConverter<T>);

...

// Having a generic method is not okay
procedure TMyForm.ShowContents<T>(List: TList<T>; Converter:
TStringConverter<T>);
var
  Item: T;
begin
  ListBox.Items.BeginUpdate;
  try
    ListBox.Items.Clear;
    for Item in List do
      ListBox.Items.Add(Converter(Item));
  finally
    ListBox.Items.EndUpdate;
  end;
end;

You can't use generics without specialization.

// This is not okay. Instead you have to specialize TList<T> and
TStringConverter<T> inside TMyTestObject<T>
procedure TMyTestObject<T>.DumpContents(List: TList<T>; Converter:
TStringConverter<T>);
var
  Item: T;
begin
  FStrings.BeginUpdate;
  try
    FStrings.Clear;
    for Item in List do
      FStrings.Add(Converter(Item));
  finally
    FStrings.EndUpdate;
  end;
end;

Specialization leads to problems, as specialized types from one class cannot
be share with another class. Also you cannot use specialization nside an
interface.

  IMyInterface<T> = interface
    function GetCurrent: T;
    // because of we specialization can't use other generics in an interface
    function CurrentString(Converter: TStringConverter<T>): string;
    procedure TakeFirst(List: TList<T>);
    property Current: T read GetCurrent;
  end;

The solution:

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:

type TMyClass = class List: TList<Integer>; end;

or

type TMyClass = class procedure CountDistinct<T>(List: List<T>); end;

or

type TMyClass = class function Combine(List: List<string>): string; end;

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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus-ide.org/pipermail/lazarus/attachments/20110829/77064168/attachment-0002.html>


More information about the Lazarus mailing list