Recent

Author Topic: syntax problem when using generics  (Read 1469 times)

VisualLab

  • Sr. Member
  • ****
  • Posts: 321
Re: syntax problem when using generics
« Reply #15 on: March 02, 2023, 07:54:16 pm »
And all of you should learn to specialize as a type not on a var.

That's what I do. I try to avoid unreadable, ambiguous or convoluted code. And for these reasons, when I use generics, I also use Delphi mode. And that's also why I asked these three questions. So far, I have barely used the specialize keyword. More precisely - I tried, but after several attempts I gave up this practice.

That is plain stupid, although it is allowed.

I think so too.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5481
  • Compiler Developer
Re: syntax problem when using generics
« Reply #16 on: March 03, 2023, 07:48:42 am »
This is a rather bizarre notation:

Code: Pascal  [Select][+][-]
  1. var
  2.   lst : fgl.specialize TFPGList<Integer>;
  3. begin
  4.   lst := fgl.specialize TFPGList<Integer>.Create;
  5. end.

Is there an alternative notation that would be more "pascalish"? For example like this:

Code: Pascal  [Select][+][-]
  1. var
  2.   lst : specialize fgl.TFPGList<Integer>;
  3. begin
  4.   lst := specialize fgl.TFPGList<Integer>.Create;
  5. end.

The first way, where the keyword specialize is "mixed in" into part of the name, is not very readable.

You are not thinking far ahead enough: the problem is if you have multiple specialization in one statement. E.g. SomeUnit.specialize SomeTypeA<TypeX>.specialize SomeTypeB<TypeY>.specialize SomeClassFunc<TypeZ>. By having the specialize be part of the identifier to be specialized things are much clearer.

Delphi mode does not use this keyword. So was it really necessary to add this keyword? Perhaps the rule of "don't multiply entities beyond necessity" should have worked here (i.e. if the syntax of the language is readable without additional syntax elements, then you probably shouldn't add them).

First of the keyword was added way before Delphi added generics. And second FPC still does not support all situations where Delphi supports specializations (e.g. expressions with inline specializations that involve operators), simply because the syntax of using “<” is ambiguous especially due to Delphi also allowing overloads of generics types with variables, constants and functions.

However, if there are any reasons to use this word, then perhaps it should appear before the type name? After all, the fgl prefix only specifies the name of the module from which this class comes (it becomes part of the type name).

No, that was originally the case, but was changed with 3.2.0 when generic functions were introduced for the above reason.

or just drop fgl. .. not the library, but the prefix
Code: Pascal  [Select][+][-]
  1. var
  2.   lst : specialize TFPGList<Integer>;

even better, declare a type first. Keeps your code cleaner.
Code: Pascal  [Select][+][-]
  1. {$mode objfpc}
  2. uses fgl;
  3. type
  4.   Tlst = specialize TFPGList<Integer>;
  5. var
  6.   lst : Tlst;
  7. begin
  8.   lst := Tlst.Create;
  9.   Lst.Free;
  10. end.

The unit prefix only makes sense if you combine multiple generics libraries, like fgl, lgenerics and or rtl-generics and all of that also in the same unit....

Also this simply won't work in FPC < 3.3.1 due to it not handling unit names together with generics correctly (it will pick the generic from one of the two units, not necessarily the one you specified, assuming it's indeed available in multiple units).

Warfley

  • Hero Member
  • *****
  • Posts: 1499
Re: syntax problem when using generics
« Reply #17 on: March 03, 2023, 08:13:55 am »
You are not thinking far ahead enough: the problem is if you have multiple specialization in one statement. E.g. SomeUnit.specialize SomeTypeA<TypeX>.specialize SomeTypeB<TypeY>.specialize SomeClassFunc<TypeZ>. By having the specialize be part of the identifier to be specialized things are much clearer.
There could be other solutions, e.g. . could have precedence over specialize, so it would be:
Code: Pascal  [Select][+][-]
  1. specialize (specialize A.B<T>).C<U>
Alternatively, specialize could be binding to the first unspecialized generic in a chain, so:
Code: Pascal  [Select][+][-]
  1. specialize specialize A.B<T>.C<U>
But I'm not sure if this is going to be better readable in chain (and is probably much harder to implement robustly in the compiler).

Or, just as a special case, when there is only one specialize, it could be put in front, and to only have specialize in chains required when more than one generic occurs:
Code: Pascal  [Select][+][-]
  1. specialize A.B<T>
  2. vs
  3. A.specialize B<T>.specialze C<U>

But TBH, while I also think this syntax isn't the prettiest, it occurs so rarely, that I don't think it is really a problem.

Thaddy

  • Hero Member
  • *****
  • Posts: 14373
  • Sensorship about opinions does not belong here.
Re: syntax problem when using generics
« Reply #18 on: March 03, 2023, 10:59:28 am »
Also this simply won't work in FPC < 3.3.1 due to it not handling unit names together with generics correctly (it will pick the generic from one of the two units, not necessarily the one you specified, assuming it's indeed available in multiple units).
Well, it does in 3.2.0 because fgl.TFPGList<> and generics.collections.Tlist<> are resolved correctly?
If not, I stand corrected, again... But that is in the context of my example not the the case because the roots differ in name.
Or, as usual, am I missing something?
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11453
  • FPC developer.
Re: syntax problem when using generics
« Reply #19 on: March 03, 2023, 11:51:04 am »
Or specialize could only be used to disambiguate instead of being mandatory.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5481
  • Compiler Developer
Re: syntax problem when using generics
« Reply #20 on: March 04, 2023, 05:23:05 pm »
Also this simply won't work in FPC < 3.3.1 due to it not handling unit names together with generics correctly (it will pick the generic from one of the two units, not necessarily the one you specified, assuming it's indeed available in multiple units).
Well, it does in 3.2.0 because fgl.TFPGList<> and generics.collections.Tlist<> are resolved correctly?
If not, I stand corrected, again... But that is in the context of my example not the the case because the roots differ in name.
Or, as usual, am I missing something?

It works in those cases, because only one TFPGList<> or TList<> exists anyway. If you have two units with a generic with the same name then you'll have the problem.

 

TinyPortal © 2005-2018