Recent

Author Topic: [SOLVED] Operator overloading (comparisons)  (Read 1863 times)

Graham1

  • Jr. Member
  • **
  • Posts: 57
[SOLVED] Operator overloading (comparisons)
« on: September 19, 2021, 06:42:33 am »
I thought I'd learn a bit about operator overloading and decided to use three value booleans (trileans, or trooleans?) as an exercise for this. I've only just started but ran into one thing that I'd like to do but I suspect isn't possible. So far my unit is:

Code: Pascal  [Select][+][-]
  1. unit trileans;
  2.  
  3. {$mode objfpc}{$modeswitch advancedrecords}{$H+}
  4.  
  5. interface
  6.  
  7. uses SysUtils;
  8.  
  9. const
  10.   no      : byte = 0;
  11.   yes     : byte = 1;
  12.   maybe   : byte = 2;
  13.   other   : byte = 2;
  14.   unknown : byte = 2;
  15.  
  16. type
  17.   Trilean = record
  18.     private
  19.       val : byte;
  20.   end;
  21.  
  22. operator := (b:byte) : trilean;
  23. operator := (b:boolean) : trilean;
  24. operator = (t:trilean; b:byte) : boolean;
  25. operator = (t:trilean; b:boolean) : boolean;
  26.  
  27. function TrilToStr(T:Trilean; UseTrilStrs:Boolean=false):string;
  28. function TrilToStr(T:Trilean; const TrueS,FalseS,OtherS:string):string;
  29.  
  30. {------------------------------------------------------------------------}
  31.  
  32. implementation
  33.  
  34. operator := (b:byte) : trilean;
  35. begin
  36.    result.val:=b;
  37. end;
  38.  
  39. operator := (b:boolean) : trilean;
  40. begin
  41.    if b then result.val:=yes else result.val:=no;
  42. end;
  43.  
  44. operator = (t:trilean; b:byte) : boolean;
  45. begin
  46.    if t.val=b then result:=true else result:=false;
  47. end;
  48.  
  49. operator = (t:trilean; b:boolean) : boolean;
  50. begin
  51.    if b     and (t.val=YES) then result:=true else
  52.    if not b and (t.val=NO)  then result:=true else
  53.                                  result:=false;
  54. end;
  55.  
  56. function TrilToStr(T:Trilean; UseTrilStrs:Boolean=false):string;
  57. begin
  58.    if UseTrilStrs then begin
  59.       if T.val=YES then result:='True' else
  60.       if T.val=NO  then result:='False' else
  61.                         result:='Other';
  62.    end else begin
  63.       result:=inttostr(T.val);
  64.    end;
  65. end;
  66.  
  67. function TrilToStr(T:Trilean; const TrueS,FalseS,OtherS:string):string;
  68. begin
  69.    if T.val=YES then result:=TrueS else
  70.    if T.val=NO  then result:=FalseS else
  71.                      result:=OtherS;
  72. end;
  73.  
  74. end.

This lets me do things like setting MyTrilean:=true or MyTrilean:=maybe and print out the trilean's values.

But I'd like the trileans to behave just like booleans but with an extra value so my problem is the comparison. I can say:

Code: Pascal  [Select][+][-]
  1. if MyTrilean=true then writeln('OK');

but I can't replace this with the neater:

Code: Pascal  [Select][+][-]
  1. if MyTrilean then writeln('OK');

The comparison operator requires two parameters and I can't think of any other way to do this. Is there a clever way to provide a function that will allow an immediate evaluation of a record based on whatever rule I choose (in this case if T.val=1)?

As I said, I suspect the answer is no but thought it would be educational to ask!

Also, since this is just a learning exercise is this the method you would use in implementing these or is there something better? I thought of using a class rather than a record but they don't seem to allow operator overloads.

Thanks.
                                         
« Last Edit: September 20, 2021, 01:08:24 am by Graham1 »
Windows 10/11 Home 64-bit (and Linux because I have to)
Lazarus 2.0.12 / FPC 3.2.0 (because libQt5pas 1.2.6)
Linux Mint 20 (because GLIBC_2.31)

ASerge

  • Hero Member
  • *****
  • Posts: 2212
Re: Operator overloading (comparisons)
« Reply #1 on: September 19, 2021, 09:03:08 am »
but I can't replace this with the neater:
Code: Pascal  [Select][+][-]
  1. if MyTrilean then writeln('OK');
Define
Code: Pascal  [Select][+][-]
  1. operator := (t: Trilean): Boolean;

Bart

  • Hero Member
  • *****
  • Posts: 5265
    • Bart en Mariska's Webstek
Re: Operator overloading (comparisons)
« Reply #2 on: September 19, 2021, 02:44:23 pm »
Why do maybe, other and unknown have the same value?
Why do you define them as "writeable constants", is the user allowed to change no to 1, and yes to 0?

Bart

Thaddy

  • Hero Member
  • *****
  • Posts: 14164
  • Probably until I exterminate Putin.
Re: Operator overloading (comparisons)
« Reply #3 on: September 19, 2021, 02:48:38 pm »
« Last Edit: September 19, 2021, 03:10:36 pm by Thaddy »
Specialize a type, not a var.

Thaddy

  • Hero Member
  • *****
  • Posts: 14164
  • Probably until I exterminate Putin.
Re: Operator overloading (comparisons)
« Reply #4 on: September 19, 2021, 03:13:33 pm »
Why do maybe, other and unknown have the same value?
Why do you define them as "writeable constants", is the user allowed to change no to 1, and yes to 0?

Bart

Because ithey all express uncertainty. They are equivent names but  part of a three way system.
See https://en.wikipedia.org/wiki/Three-valued_logic

(btw, my older one is a  more complete verion of Kleene and Priest)
« Last Edit: September 19, 2021, 03:15:56 pm by Thaddy »
Specialize a type, not a var.

Graham1

  • Jr. Member
  • **
  • Posts: 57
[SOLVED] Operator overloading (comparisons)
« Reply #5 on: September 20, 2021, 01:07:59 am »
Define
Code: Pascal  [Select][+][-]
  1. operator := (t: Trilean): Boolean;

Of course! It's quite obvious really - once somebody shows the answer!! Thank you so much, that fixed it and also taught me that assignments are useful not just in setting the values but also in accessing them.

Why do maybe, other and unknown have the same value?
Why do you define them as "writeable constants", is the user allowed to change no to 1, and yes to 0?

As Thaddy says, it's because a trilean has three values. Normally I would use an enumerated list for this but then I would be stuck with the names I chose at the design of this unit. But just because something has three values doesn't mean the third is always "unknown":

Have I won the lottery: Yes, No, I'll find out tonight!
What shape is this: Square, Circle, Something else
The cat in the box is alive: True, False, Both

So I used constants as they are easily added to without changing the actual values used (which are hidden as Val is private). At the same time I also wanted to be able to use the trileans like real booleans to access the true/false (yes/no) values, which is why I wanted ASerge's answer.

Because ithey all express uncertainty. They are equivent names but  part of a three way system.
See https://en.wikipedia.org/wiki/Three-valued_logic

(btw, my older one is a  more complete verion of Kleene and Priest)

I suspected I was reinventing the wheel, but as I mentioned this was an excuse to learn about overrides. I didn't realise trileans/trinaries/... had such an interesting history and so much theory though! If I'd read all that first I might never have started!!

Thank you everyone for your interesting and helpful replies.
Windows 10/11 Home 64-bit (and Linux because I have to)
Lazarus 2.0.12 / FPC 3.2.0 (because libQt5pas 1.2.6)
Linux Mint 20 (because GLIBC_2.31)

Graham1

  • Jr. Member
  • **
  • Posts: 57
Re: [SOLVED] Operator overloading (comparisons)
« Reply #6 on: September 22, 2021, 01:39:42 am »
I thought I might as well post my 'finished' version:

Code: Pascal  [Select][+][-]
  1. unit trileans;
  2.  
  3. {$mode objfpc}{$modeswitch advancedrecords}{$H+}
  4.  
  5. interface
  6.  
  7. uses SysUtils;
  8.  
  9. const
  10.   no      : byte = 0;
  11.   yes     : byte = 1;
  12.   other   : byte = 2;
  13.   maybe   : byte = 2;
  14.   unknown : byte = 2;
  15.  
  16. type
  17.   Trilean = record
  18.     private
  19.       val : byte;
  20.   end;
  21.  
  22. operator := (b:byte) : trilean;
  23. operator := (b:boolean) : trilean;
  24. operator := (t:trilean) : boolean;
  25. operator := (t:trilean) : string;
  26.  
  27. operator = (t:trilean; b:byte) : boolean;
  28. operator = (t:trilean; b:boolean) : boolean;
  29.  
  30. operator + (t:trilean; s:string) : string;
  31. operator + (s:string; t:trilean) : string;
  32.  
  33. operator not (t:trilean) : trilean;
  34. operator and (t1,t2:trilean) : trilean;
  35. operator or  (t1,t2:trilean) : trilean;
  36. operator xor (t1,t2:trilean) : trilean;
  37.  
  38. operator inc (t:trilean) : trilean;
  39. operator dec (t:trilean) : trilean;
  40.  
  41.  
  42. function TrilToStr(T:Trilean; UseTrilStrs:Boolean=false):string;
  43. function TrilToStr(T:Trilean; const TrueS,FalseS,OtherS:string):string;
  44.  
  45. {------------------------------------------------------------------------}
  46.  
  47. implementation
  48.  
  49. operator := (b:byte) : trilean;
  50. begin
  51.    if (b=YES) or (b=NO) or (b=OTHER) then result.val:=b;
  52. end;
  53.  
  54. operator := (b:boolean) : trilean;
  55. begin
  56.    if b then result.val:=YES else result.val:=NO;
  57. end;
  58.  
  59. operator := (t:trilean) : boolean;
  60. begin
  61.    if t.val=YES then result:=true else result:=false;
  62. end;
  63.  
  64. operator := (t:trilean) : string;
  65. begin
  66.    if t.val=YES then result:='TRUE' else
  67.    if t.val=NO  then result:='FALSE' else
  68.                      result:='OTHER';
  69. end;
  70.  
  71. operator = (t:trilean; b:byte) : boolean;
  72. begin
  73.    if t.val=b then result:=true else result:=false;
  74. end;
  75.  
  76. operator = (t:trilean; b:boolean) : boolean;
  77. begin
  78.    if b     and (t.val=YES) then result:=true else
  79.    if not b and (t.val=NO)  then result:=true else
  80.                                  result:=false;
  81. end;
  82.  
  83. operator + (t:trilean; s:string) : string;
  84. begin
  85.    if t.val=YES then result:='TRUE'+s else
  86.    if t.val=NO  then result:='FALSE'+s else
  87.                      result:='OTHER'+s;
  88. end;
  89.  
  90. operator + (s:string; t:trilean) : string;
  91. begin
  92.    if t.val=YES then result:=s+'TRUE' else
  93.    if t.val=NO  then result:=s+'FALSE' else
  94.                      result:=s+'OTHER';
  95. end;
  96.  
  97. operator not (t:trilean) : trilean;
  98. begin
  99.    if T.val=YES then result.val:=NO  else
  100.    if T.val=NO  then result.val:=YES else
  101.                      result.val:=OTHER;
  102. end;
  103.  
  104. operator and (t1,t2:trilean) : trilean;
  105. begin
  106.    if (t1.val=NO) or (t2.val=NO)    then result.val:=NO else
  107.    if (t1.val=YES) and (t2.val=YES) then result.val:=YES else
  108.                                          result.val:=OTHER;
  109. end;
  110.  
  111. operator or (t1,t2:trilean) : trilean;
  112. begin
  113.    if (t1.val=YES) or (t2.val=YES) then result.val:=YES else
  114.    if (t1.val=NO) and (t2.val=NO)  then result.val:=NO else
  115.                                         result.val:=OTHER;
  116. end;
  117.  
  118. operator xor (t1,t2:trilean) : trilean;
  119. begin
  120.    if (t1.val=YES) and (t2.val=NO)  then result.val:=YES else
  121.    if (t1.val=NO)  and (t2.val=YES) then result.val:=YES else
  122.    if (t1.val=YES) and (t2.val=YES) then result.val:=NO else
  123.    if (t1.val=NO)  and (t2.val=NO)  then result.val:=NO else
  124.                                          result.val:=OTHER;
  125. end;
  126.  
  127. operator inc (t:trilean) : trilean;
  128. begin
  129.    if t.val=NO    then result.val:=OTHER else
  130.    if t.val=OTHER then result.val:=YES   else
  131.                        result.val:=t.val;
  132. end;
  133.  
  134. operator dec (t:trilean) : trilean;
  135. begin
  136.    if t.val=YES   then result.val:=OTHER else
  137.    if t.val=OTHER then result.val:=NO    else
  138.                        result.val:=t.val;
  139. end;
  140.  
  141.  
  142. function TrilToStr(T:Trilean; UseTrilStrs:Boolean=false):string;
  143. begin
  144.    if UseTrilStrs then begin
  145.       if T.val=YES then result:='True' else
  146.       if T.val=NO  then result:='False' else
  147.                         result:='Other';
  148.    end else begin
  149.       result:=inttostr(T.val);
  150.    end;
  151. end;
  152.  
  153. function TrilToStr(T:Trilean; const TrueS,FalseS,OtherS:string):string;
  154. begin
  155.    if T.val=YES then result:=TrueS else
  156.    if T.val=NO  then result:=FalseS else
  157.                      result:=OtherS;
  158. end;
  159.  
  160.  
  161. end.

This can be used like booleans but with an extra value, for example:

Code: Pascal  [Select][+][-]
  1. program TrileanUse;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses trileans;
  6.  
  7. var
  8.   tr1, tr2 : trilean;
  9.   i, j     : byte;
  10.   ab       : array[1..3] of byte;
  11.  
  12. begin
  13.  
  14.   tr1:=maybe;
  15.   write('tr1 set to MAYBE. tr1 is now: ');
  16.   writeln(TriltoStr(tr1,true));
  17.  
  18.   tr2:=tr1;
  19.   writeln('tr1 copied to tr2');
  20.  
  21.   tr1:=true;
  22.   write('tr1 set to TRUE. tr1 is now: ');
  23.   writeln(TriltoStr(tr1,true));
  24.  
  25.   write('tr2 is still: ');
  26.   writeln(TriltoStr(tr2,true));
  27.  
  28.   if tr1 then writeln('Is tr1 true? Yes') else writeln('Is tr1 true? No');
  29.   if not tr1 then writeln('Is tr1 false? Yes') else writeln('Is tr1 false? No');
  30.   if tr1 or not tr1 then writeln('tr1 is Known') else writeln('tr1 is Unknown');
  31.  
  32.   tr1:=other;
  33.   writeln('tr1 set to OTHER');
  34.   if tr1 then writeln('Is tr1 true? Yes') else writeln('Is tr1 true? No');
  35.   if not tr1 then writeln('Is tr1 false? Yes') else writeln('Is tr1 false? No');
  36.   if tr1 or not tr1 then writeln('tr1 is Known') else writeln('tr1 is Unknown');
  37.   writeln;
  38.  
  39.   ab[1]:=NO;
  40.   ab[2]:=OTHER;
  41.   ab[3]:=YES;
  42.  
  43.   writeln(' NOT      AND F O T     OR  F O T     XOR F O T      INC       DEC');
  44.  
  45.   for i in ab do begin
  46.     tr1:=i;
  47.     write(' '+TrilToStr(tr1,'T','F','O'));
  48.  
  49.     tr2:=not tr1;
  50.     write('  '+TrilToStr(tr2,'t','f','o'));
  51.  
  52.     write('      '+TrilToStr(tr1,'T','F','O')+' ');
  53.     for j in ab do begin
  54.        tr2:=j;
  55.        write(' '+TrilToStr(tr1 and tr2,'t','f','o'));
  56.     end;
  57.  
  58.     write('      '+TrilToStr(tr1,'T','F','O')+' ');
  59.     for j in ab do begin
  60.        tr2:=j;
  61.        write(' '+TrilToStr(tr1 or tr2,'t','f','o'));
  62.     end;
  63.  
  64.     write('      '+TrilToStr(tr1,'T','F','O')+' ');
  65.     for j in ab do begin
  66.        tr2:=j;
  67.        write(' '+TrilToStr(tr1 xor tr2,'t','f','o'));
  68.     end;
  69.  
  70.     write('      '+TrilToStr(tr1,'T','F','O')+' ');
  71.     tr2:=tr1;
  72.     inc(tr2);
  73.     write(' '+TrilToStr(tr2,'t','f','o'));
  74.  
  75.     write('      '+TrilToStr(tr1,'T','F','O')+' ');
  76.     tr2:=tr1;
  77.     dec(tr2);
  78.     write(' '+TrilToStr(tr2,'t','f','o'));
  79.  
  80.     writeln;
  81.   end;
  82.  
  83.   writeln;
  84.   writeln('Press enter to quit');
  85.   readln;
  86.  
  87. end.

This outputs:

Code: Text  [Select][+][-]
  1. tr1 set to MAYBE. tr1 is now: Other
  2. tr1 copied to tr2
  3. tr1 set to TRUE. tr1 is now: True
  4. tr2 is still: Other
  5. Is tr1 true? Yes
  6. Is tr1 false? No
  7. tr1 is Known
  8. tr1 set to OTHER
  9. Is tr1 true? No
  10. Is tr1 false? No
  11. tr1 is Unknown
  12.  
  13.  NOT      AND F O T     OR  F O T     XOR F O T      INC       DEC
  14.  F  t      F  f f f      F  f o t      F  f o t      F  o      F  f
  15.  O  o      O  f o o      O  o o t      O  o o o      O  t      O  f
  16.  T  f      T  f o t      T  t t t      T  t o f      T  t      T  o

Thank you everyone for your help.

Windows 10/11 Home 64-bit (and Linux because I have to)
Lazarus 2.0.12 / FPC 3.2.0 (because libQt5pas 1.2.6)
Linux Mint 20 (because GLIBC_2.31)

 

TinyPortal © 2005-2018