Discussion:
[fpc-pascal] Background info on Generics in FPC
Graeme Geldenhuys via fpc-pascal
2021-04-17 19:07:59 UTC
Permalink
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
_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
https://lists
Florian Klämpfl via fpc-pascal
2021-04-17 19:20:37 UTC
Permalink
Post by 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.

_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
https://lists.freep
Ryan Joseph via fpc-pascal
2021-04-17 19:56:11 UTC
Permalink
Post by 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?
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

_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/
Sven Barth via fpc-pascal
2021-04-17 21:19:29 UTC
Permalink
Post by Graeme Geldenhuys via fpc-pascal
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
_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pasca
Graeme Geldenhuys via fpc-pascal
2021-04-18 15:59:32 UTC
Permalink
Post by Sven Barth via fpc-pascal
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
_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
https://lists.freep

Loading...