Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2021-04

Background info on Generics in FPC

5 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Graeme Geldenhuys

Hi

I'm looking at the wiki and official FPC language documentation. What was the reason for the decision to make the FPC syntax so verbose regarding Generics?

eg: What we have now....

type
  generic TArray<t> = array of t;
  TMyIntegerArray = specialize TArray<integer>;
  generic IList<_T> = Interface
    Function GetItem(AIndex : Integer) : _T;
    Procedure SetItem(AIndex : Integer; AValue : _T);
    Function GetCount : Integer;
    Property Items [AIndex : Integer] : _T Read GetItem Write SetItem;
    Property Count : Integer Read GetCount;
  end;
  generic TList<_T>=class(TObject, specialize IList<_T>)
  public type
    TCompareFunc = function(const Item1, Item2: _T): Integer;
    Function GetItem(AIndex : Integer) : _T;
    Procedure SetItem(AIndex : Integer; AValue : _T);
    Function GetCount : Integer;
  Public
     data : _T;
     procedure Add(item: _T);
     procedure Sort(compare: TCompareFunc);
  end;

Why couldn't it have been made less verbose like this:

type
  TArray<t> = array of t;
  TMyIntegerArray = TArray<integer>;
  IList<_T> = Interface
    Function GetItem(AIndex : Integer) : _T;
    Procedure SetItem(AIndex : Integer; AValue : _T);
    Function GetCount : Integer;
    Property Items [AIndex : Integer] : _T Read GetItem Write SetItem;
    Property Count : Integer Read GetCount;
  end;
  TList<_T>=class(TObject, IList<_T>)
  public type
    TCompareFunc = function(const Item1, Item2: _T): Integer;
    Function GetItem(AIndex : Integer) : _T;
    Procedure SetItem(AIndex : Integer; AValue : _T);
    Function GetCount : Integer;
  Public
     data : _T;
     procedure Add(item: _T);
     procedure Sort(compare: TCompareFunc);
  end;

Out of curiosity I would like to understand the reasoning behind the verbose usage of the keywords `generic` and `specialize`.

Regards,
Graeme

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp

Reply by email

Florian Klämpfl
to Graeme Geldenhuys
Show quoted text 7 lines
Am 17.04.2021 um 21:07 schrieb Graeme Geldenhuys via fpc-pascal : Hi I'm looking at the wiki and official FPC language documentation. What was the reason for the decision to make the FPC syntax so verbose regarding Generics?

Same reason why we have

a : array[0..10] of integer;

instead of

a : integer[0..10];

After all, using the keywords generic and specialize felt more pascalish to us.

Reply by email

Ryan Joseph
to Graeme Geldenhuys: Hi I'm looking at the wiki and official FPC language documentation. What was the reason…
Show quoted text 7 lines
On Apr 17, 2021, at 1:07 PM, Graeme Geldenhuys via fpc-pascal wrote: Hi I'm looking at the wiki and official FPC language documentation. What was the reason for the decision to make the FPC syntax so verbose regarding Generics?

There is a plan to make these optional via a mode switch but it hasn't happened yet. Personally I like the "generic" keyword but the specialize keyword is annoying if you don't make a type alias (and for function calls of course). Implicit function specialization is already ready so at least we won't need to use at all for function calls.

Regards,
Ryan Joseph

Reply by email

Sven Barth
to Graeme Geldenhuys: Hi I'm looking at the wiki and official FPC language documentation. What was the reason…
Graeme Geldenhuys wrote
I'm looking at the wiki and official FPC language documentation. What was the reason for the decision to make the FPC syntax so verbose regarding Generics?

I don't know what the original reason was, but nowadays it's main advantage is that it avoids ambiguity. Take the following code:

=== code begin ===

someint := SomeGeneric<SomeType> + 42;

=== code end ===

The problem is that Delphi allows overloading of generic types with non-generic types, variables, constants and routines, thus up until the SomeType the code could in fact be the following as well:

=== code begin ===

var
   SomeType,
   SomeGeneric: LongInt;
   someint: Boolean;
begin
   someint := SomeGeneric<SomeType;
end;

=== code end ===

The compiler's parser has a very limited look ahead and thus especially with more complex specializations (especially nested ones) and type overloads in scope the compiler might not come to the right decision (e.g. it decided to parse it as a specialization, but it should have been a non-generic expression instead) and then it would need to do back tracking.

Delphi's parser handles such cases correctly, but FPC's parser is currently simply not capable of that. Thus the "specialize" keyword definitely helps to differentiate between a non-generic expression and a specialization. This also means that the non-Delphi modes currently can handle more complex expressions involving generics than mode Delphi can.

And for the "generic" keyword one could say that this way it is clear that one can't use the type as is and instead one must specialize them (also remember that originaly FPC did not support inline specializations; instead you had to do a type declaration for each specialization you wanted).

Regards,
Sven

Reply by email

Graeme Geldenhuys
to Sven Barth
Sven Barth wrote
The compiler's parser has a very limited look ahead and thus especially with more complex specializations (especially nested ones) and type overloads in scope the compiler might not come to the right decision

OK, that and the "it's more Pascal-like syntax" make sense.

Thanks everyone for your answers.

Regards,
Graeme

Reply by email