[SOLVED]Generics and Include/Exclude lazarus / 62-General ---------------------------------------------------------------------- avk · 2020-09-22 11:18 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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program test; {$mode delphi} type  TElem = (One, Two, Three, Four, Five);  TSet  = set of TElem; procedure TurnSetElem(var aSet: TSet; aElem: TElem; aOn: Boolean);begin  if aOn then    Include(aSet, aElem)  else    Exclude(aSet, aElem);end; var  s: TSet = [];  e: TElem; begin  for e in s do    WriteLn(e);  TurnSetElem(s, Two, True);  TurnSetElem(s, Five, True);  for e in s do    WriteLn(e);end.  compile-time error(both 3.2.0 and 3.3.1): Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i test.lpr(12,5) Error: Type mismatchtest.lpr(14,5) Error: Type mismatch  But if the procedure is slightly changed: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TurnSetElem(var aSet: TSet; aElem: TElem; aOn: Boolean);begin  if aOn then    aSet += [aElem]  else    aSet -= [aElem] ;end;  then it compiles and works as expected. Why is there such discrimination? ---------------------------------------------------------------------- ASerge · 2020-09-22 18:07 Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$APPTYPE CONSOLE}{$MODE DELPHI} procedure TurnSetElem(var ASet: TSet; AElem: TElem; AOn: Boolean);   procedure TurnSetUniveral(var ASet; const AItem; AOn: Boolean);  type    TItem = 0..31;    TItemSet = set of TItem;  begin    if AOn then      Include(TItemSet(ASet), TItem(AItem))    else      Exclude(TItemSet(ASet), TItem(AItem))  end; begin  TurnSetUniveral(ASet, AElem, AOn)end; procedure Test;type  TElem = (One, Two, Three, Four, Five);  TSet  = set of TElem;var  LSet: TSet = [];  Elem: TElem;begin  for Elem in LSet do    WriteLn(Elem);  TurnSetElem(LSet, Two, True);  TurnSetElem(LSet, Five, True);  for Elem in LSet do    WriteLn(Elem);end; begin  Test;  Readln;end. ---------------------------------------------------------------------- avk · 2020-09-23 04:26 @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. ---------------------------------------------------------------------- ASerge · 2020-09-23 14:45 Quote from: avk on September 23, 2020, 06:26:15 amBut 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 · 2020-09-23 17:23 Quote from: ASerge on September 23, 2020, 04:45:05 pmBuilt-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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function GenSumOrd(a, b: T): T;begin  Result := Ord(a) + Ord(b);end;  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 · 2020-09-23 20:02 Quote from: avk on September 22, 2020, 01:18:20 pmWhy 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 · 2020-09-24 03:50 Thank you, done. BTW, what about this case? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i type  TSetUtil = record  type    TSet = set of TElem;    class procedure TurnElem(var aSet: TSet; aElem: TElem; aOn: Boolean); static;  end; ---------------------------------------------------------------------- Thaddy · 2020-09-24 06:29 Note you may be able to use the new generic ifthen<> from sysutils in such a way? 3.2.0 + ---------------------------------------------------------------------- PascalDragon · 2020-09-24 07:16 Quote from: avk on September 24, 2020, 05:50:36 amThank you, done. Thank you. Quote from: avk on September 24, 2020, 05:50:36 amBTW, 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 · 2020-09-24 08:14 Quote from: Thaddy on September 24, 2020, 08:29:29 amNote 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? Quote from: PascalDragon on September 24, 2020, 09:16:45 amI 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 · 2020-09-24 09:42 Quote from: avk on September 24, 2020, 10:14:08 amI 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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i generic function IfThen(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. ---------------------------------------------------------------------- PascalDragon · 2020-09-24 11:58 Quote from: avk on September 24, 2020, 10:14:08 amQuote from: PascalDragon on September 24, 2020, 09:16:45 amI 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 · 2020-09-25 15:32 @PascalDragon, thanks a lot. The procedure now compiles and works as expected. But will these changes be merged in 3.2.1? ---------------------------------------------------------------------- PascalDragon · 2020-09-26 08:00 I'll ask for them to be merged, yes, they shouldn't be that invasive.