Recent

Author Topic: [SOLVED]Generics and Include/Exclude  (Read 2615 times)

avk

  • Hero Member
  • *****
  • Posts: 752
[SOLVED]Generics and Include/Exclude
« on: September 22, 2020, 01:18:20 pm »
Suppose we need a procedure that, depending on the condition, includes or excludes a given element from the set and we want the procedure to accept any type of set as a parameter. Using a generic procedure for this seems like a good option:
Code: Pascal  [Select][+][-]
  1. program test;
  2.  
  3. {$mode delphi}
  4.  
  5. type
  6.   TElem = (One, Two, Three, Four, Five);
  7.   TSet  = set of TElem;
  8.  
  9. procedure TurnSetElem<TSet, TElem>(var aSet: TSet; aElem: TElem; aOn: Boolean);
  10. begin
  11.   if aOn then
  12.     Include(aSet, aElem)
  13.   else
  14.     Exclude(aSet, aElem);
  15. end;
  16.  
  17. var
  18.   s: TSet = [];
  19.   e: TElem;
  20.  
  21. begin
  22.   for e in s do
  23.     WriteLn(e);
  24.   TurnSetElem<TSet, TElem>(s, Two, True);
  25.   TurnSetElem<TSet, TElem>(s, Five, True);
  26.   for e in s do
  27.     WriteLn(e);
  28. end.
  29.  
compile-time error(both 3.2.0 and 3.3.1):
Code: Text  [Select][+][-]
  1. test.lpr(12,5) Error: Type mismatch
  2. test.lpr(14,5) Error: Type mismatch
  3.  

But if the procedure is slightly changed:
Code: Pascal  [Select][+][-]
  1. procedure TurnSetElem<TSet, TElem>(var aSet: TSet; aElem: TElem; aOn: Boolean);
  2. begin
  3.   if aOn then
  4.     aSet += [aElem]
  5.   else
  6.     aSet -= [aElem] ;
  7. end;
  8.  
then it compiles and works as expected.

Why is there such discrimination?
« Last Edit: September 25, 2020, 05:36:15 pm by avk »

ASerge

  • Hero Member
  • *****
  • Posts: 2212
Re: Generics and Include/Exclude
« Reply #1 on: September 22, 2020, 08:07:36 pm »
Code: Pascal  [Select][+][-]
  1. {$APPTYPE CONSOLE}
  2. {$MODE DELPHI}
  3.  
  4. procedure TurnSetElem<TSet, TElem>(var ASet: TSet; AElem: TElem; AOn: Boolean);
  5.  
  6.   procedure TurnSetUniveral(var ASet; const AItem; AOn: Boolean);
  7.   type
  8.     TItem = 0..31;
  9.     TItemSet = set of TItem;
  10.   begin
  11.     if AOn then
  12.       Include(TItemSet(ASet), TItem(AItem))
  13.     else
  14.       Exclude(TItemSet(ASet), TItem(AItem))
  15.   end;
  16.  
  17. begin
  18.   TurnSetUniveral(ASet, AElem, AOn)
  19. end;
  20.  
  21. procedure Test;
  22. type
  23.   TElem = (One, Two, Three, Four, Five);
  24.   TSet  = set of TElem;
  25. var
  26.   LSet: TSet = [];
  27.   Elem: TElem;
  28. begin
  29.   for Elem in LSet do
  30.     WriteLn(Elem);
  31.   TurnSetElem<TSet, TElem>(LSet, Two, True);
  32.   TurnSetElem<TSet, TElem>(LSet, Five, True);
  33.   for Elem in LSet do
  34.     WriteLn(Elem);
  35. end;
  36.  
  37. begin
  38.   Test;
  39.   Readln;
  40. end.

avk

  • Hero Member
  • *****
  • Posts: 752
Re: Generics and Include/Exclude
« Reply #2 on: September 23, 2020, 06:26:15 am »
@ASerge, yeah, I've already seen code like this in this post. But the question is that the fact that the compiler does not accept Include/Exclude looks like a bug.
« Last Edit: September 23, 2020, 11:34:53 am by avk »

ASerge

  • Hero Member
  • *****
  • Posts: 2212
Re: Generics and Include/Exclude
« Reply #3 on: September 23, 2020, 04:45:05 pm »
But the question is that the fact that the compiler does not accept Include/Exclude looks like a bug.
I thought you needed a general solution. And the question is not difficult to answer. Built-in functions Include and Exclude expect only sets. The addition operation can be overloaded, i.e. it is valid.

avk

  • Hero Member
  • *****
  • Posts: 752
Re: Generics and Include/Exclude
« Reply #4 on: September 23, 2020, 07:23:14 pm »
Built-in functions Include and Exclude expect only sets.

And what does it get if not a set?
Some time ago, such a stupid function(containing the built-in function Ord(), which accepts only ordinals)
Code: Pascal  [Select][+][-]
  1. function GenSumOrd<T>(a, b: T): T;
  2. begin
  3.   Result := Ord(a) + Ord(b);
  4. end;
  5.  
flatly refused to compile with any version of the compiler. It now compiles(if specialized with ordinal type), at least using a trunk compiler(it looks like the changes weren't merged in 3.2.1). It seems with Include/Exclude the same situation.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5444
  • Compiler Developer
Re: Generics and Include/Exclude
« Reply #5 on: September 23, 2020, 10:02:04 pm »
Why is there such discrimination?

The thing is that intrinsics are made aware of generics on a case by case base. This way we can ensure that they handle generics as type safe as reasonably possible. In this case no one had needed them up to now, so no one implemented them.

Thus please report this as a bug.

avk

  • Hero Member
  • *****
  • Posts: 752
Re: Generics and Include/Exclude
« Reply #6 on: September 24, 2020, 05:50:36 am »
Thank you, done.

BTW, what about this case?
Code: Pascal  [Select][+][-]
  1. type
  2.   TSetUtil<TElem> = record
  3.   type
  4.     TSet = set of TElem;
  5.     class procedure TurnElem(var aSet: TSet; aElem: TElem; aOn: Boolean); static;
  6.   end;
  7.  
« Last Edit: September 24, 2020, 10:16:40 am by avk »

Thaddy

  • Hero Member
  • *****
  • Posts: 14157
  • Probably until I exterminate Putin.
Re: Generics and Include/Exclude
« Reply #7 on: September 24, 2020, 08:29:29 am »
Note you may be able to use the new generic ifthen<> from sysutils in such a way? 3.2.0 +
Specialize a type, not a var.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5444
  • Compiler Developer
Re: Generics and Include/Exclude
« Reply #8 on: September 24, 2020, 09:16:45 am »
Thank you, done.

Thank you.

BTW, what about this case?

I had thought a bit about that as well. Maybe I should adjust some restrictions a bit considering that we have a more template-like approach anyway.

avk

  • Hero Member
  • *****
  • Posts: 752
Re: Generics and Include/Exclude
« Reply #9 on: September 24, 2020, 10:14:08 am »
Note you may be able to use the new generic ifthen<> from sysutils in such a way?

I cannot figure out how I could use IfThen in this case. Maybe you can suggest some way?

I had thought a bit about that as well. Maybe I should adjust some restrictions a bit considering that we have a more template-like approach anyway.

Is something required of me?

Thaddy

  • Hero Member
  • *****
  • Posts: 14157
  • Probably until I exterminate Putin.
Re: Generics and Include/Exclude
« Reply #10 on: September 24, 2020, 11:42:16 am »
I cannot figure out how I could use IfThen in this case. Maybe you can suggest some way?
Well, the idea is that the generic ifthen can take functional and procedural parameters to allow different execution paths.

That is how I designed it.

Afaik Michael has also added an example to the documentation for that based on my own example when I submitted that feature.
It may take a little redesign of your code, but to me it looks possible.
The signature is like this:
Code: Pascal  [Select][+][-]
  1. generic function IfThen<T>(val:boolean;const iftrue:T; const iffalse:T) :T; inline; overload;
Where T can be anything, including procedural/functional types.

As usual, what Sven suggested gives even more options if implemented.
« Last Edit: September 24, 2020, 11:44:11 am by Thaddy »
Specialize a type, not a var.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5444
  • Compiler Developer
Re: Generics and Include/Exclude
« Reply #11 on: September 24, 2020, 01:58:25 pm »
I had thought a bit about that as well. Maybe I should adjust some restrictions a bit considering that we have a more template-like approach anyway.

Is something required of me?

No, not really. :)

avk

  • Hero Member
  • *****
  • Posts: 752
Re: Generics and Include/Exclude
« Reply #12 on: September 25, 2020, 05:32:37 pm »
@PascalDragon, thanks a lot. The procedure now compiles and works as expected. But will these changes be merged in 3.2.1?

PascalDragon

  • Hero Member
  • *****
  • Posts: 5444
  • Compiler Developer
Re: [SOLVED]Generics and Include/Exclude
« Reply #13 on: September 26, 2020, 10:00:27 am »
I'll ask for them to be merged, yes, they shouldn't be that invasive.

 

TinyPortal © 2005-2018