Recent

Author Topic: Is there a conditional Set that uses a boolean in a single function call ?  (Read 3363 times)

jamie

  • Hero Member
  • *****
  • Posts: 6090
You have Include and Exclude and all the inline stuff..

I was looking for a ready made conditional set.

For example..

SetSet(TheSetVariable, TheValueMember, True/False);

The idea is to either Set a member in a set or unset it with a single call.

Currently I have to do a Boolean test and branch from that to choose either Include or Exclude, but I have values coming from CheckBoxes, config files etc and it would be nice to do this in a single shot where it would either Set a member or remove it in a single step.

 How do I do that?
The only true wisdom is knowing you know nothing

Blaazen

  • Hero Member
  • *****
  • Posts: 3237
  • POKE 54296,15
    • Eye-Candy Controls
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

jamie

  • Hero Member
  • *****
  • Posts: 6090
Re: Is there a conditional Set that uses a boolean in a single function call ?
« Reply #2 on: September 20, 2020, 10:30:07 pm »
I was hoping for a non typed way of doing this without all the casting etc.

There  should be an intrinsic way to do this conditionally and the compiler will adjust the type needed.

For the time being I placed a procedure In the Class I am creating that does this .
Code: Pascal  [Select][+][-]
  1. Function TExCanvas.SetCanvasMode(AValue:TExCanvasMode; Acondition:Boolean):TExCanvasModes;
  2. Begin
  3.   Case ACondition of
  4.    False :Exclude(FCanvasModes,AValue);
  5.    True  :InClude(FCanvasModes,AValue);
  6.   end;
  7.  Result := fcanvasModes;
  8. end;                  
  9.  
The only true wisdom is knowing you know nothing

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: Is there a conditional Set that uses a boolean in a single function call ?
« Reply #3 on: September 21, 2020, 08:04:22 am »
The casts are one of the problems, but it should be possible to work around that using a generic (non-class) function... do those inline properly? C/C++ programmers would of course use a macro.

More of a problem is the conditionals which can cause a pipeline stall, hence the traditional use of a sequence of and/or/nots.

It can of course be simpler to first clear the bit, then to toggle it using xor.

MarkMLl

p.s. Happy Autumnal Equinox, everybody :-)
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

avk

  • Hero Member
  • *****
  • Posts: 752
Re: Is there a conditional Set that uses a boolean in a single function call ?
« Reply #4 on: September 21, 2020, 09:27:33 am »
Something like this?
Code: Pascal  [Select][+][-]
  1. ...
  2.  {$mode delphi}
  3. ...
  4. procedure TurnSetItem<TSet, TItem>(var aSet: TSet; aItem: TItem; aOn: Boolean); inline;
  5. ...
  6. implementation
  7. ...
  8. procedure TurnSetItem<TSet, TItem>(var aSet: TSet; aItem: TItem; aOn: Boolean);
  9. begin
  10.   if aOn then
  11.     aSet += [aItem]
  12.   else
  13.     aSet -= [aItem];
  14. end;
  15.  

egsuh

  • Hero Member
  • *****
  • Posts: 1273
Re: Is there a conditional Set that uses a boolean in a single function call ?
« Reply #5 on: September 21, 2020, 09:37:20 am »
AFAIK, Sets of Pascal can contain only ordinal types, within 0..255. So if any value may have minus (-) values, then sets do not operate correctly.  I think you may consider using TList or TFPGMap, etc.

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: Is there a conditional Set that uses a boolean in a single function call ?
« Reply #6 on: September 21, 2020, 11:11:54 am »
Hi!

Good old cast solution:

Code: Pascal  [Select][+][-]
  1. uses .......,UITypes;
  2. ......
  3. type setOfByte = set of byte;
  4.  
  5. procedure TurnSetItem (var setofSomething; var Something; aOn : boolean );
  6. begin
  7.   if aOn then
  8.     setOfByte(setOfSomething) += [byte(Something)]
  9.   else
  10.     setOfByte(setOfSomething) -= [byte(SomeThing)];
  11. end;
  12.  
  13. procedure TForm1.Button4Click(Sender: TObject);
  14. var buttons:  TMsgDlgButtons;
  15. B : TMsgDlgBtn;
  16. S: string='';
  17. SItem : string;
  18. begin
  19. buttons := [mbYes, mbNo, mbCancel];
  20. B := mbCancel;
  21. TurnSetitem (buttons, B,false);
  22. for B in buttons do
  23.    begin
  24.    writeStr(sItem,B);
  25.    s := s+SItem + ' ';
  26.    end;
  27. showMessage (s);
  28. end;
  29.  

Winni
« Last Edit: September 21, 2020, 11:25:17 am by winni »

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: Is there a conditional Set that uses a boolean in a single function call ?
« Reply #7 on: September 21, 2020, 12:20:50 pm »
Winni: I don't think that is endian safe.

Thaddy

  • Hero Member
  • *****
  • Posts: 14204
  • Probably until I exterminate Putin.
Re: Is there a conditional Set that uses a boolean in a single function call ?
« Reply #8 on: September 21, 2020, 12:30:03 pm »
Set operators can be overriden.  I believe I already posted such a solution.
Specialize a type, not a var.

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: Is there a conditional Set that uses a boolean in a single function call ?
« Reply #9 on: September 21, 2020, 01:46:40 pm »
Winni: I don't think that is endian safe.

Hi!

I don't see the endian trap.
Can you show it to me?

Winni

avk

  • Hero Member
  • *****
  • Posts: 752
Re: Is there a conditional Set that uses a boolean in a single function call ?
« Reply #10 on: September 21, 2020, 03:26:17 pm »
AFAIK, Sets of Pascal can contain only ordinal types, within 0..255. So if any value may have minus (-) values, then sets do not operate correctly.

Now these limitations can be easily overcome. For example this code:
Code: Pascal  [Select][+][-]
  1. program test_set;
  2. {$mode delphi}
  3. uses
  4.   LGUtils;
  5. type
  6.   TRange = -150..150;
  7. var
  8.   s: TGSet<TRange>;
  9.   I: TRange;
  10. begin
  11.   for I in TRange do
  12.     if I mod 20 = 0 then
  13.       s.Include(I);
  14.   for I in TRange do
  15.     if (I mod 20 = 0) and not(I in s) then
  16.       WriteLn('Ololo!');
  17.   for I in s do
  18.     WriteLn(I);
  19. end.
  20.  
prints
Code: Text  [Select][+][-]
  1. -140
  2. -120
  3. -100
  4. -80
  5. -60
  6. -40
  7. -20
  8. 0
  9. 20
  10. 40
  11. 60
  12. 80
  13. 100
  14. 120
  15. 140
  16.  
« Last Edit: September 21, 2020, 03:42:56 pm by avk »

Blaazen

  • Hero Member
  • *****
  • Posts: 3237
  • POKE 54296,15
    • Eye-Candy Controls
Re: Is there a conditional Set that uses a boolean in a single function call ?
« Reply #11 on: September 21, 2020, 07:54:43 pm »
I found quite nice way to switch any set of enumeration:
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2. {$mode objfpc}{$H+}
  3.  
  4. interface
  5.  
  6. uses
  7.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
  8.  
  9. type
  10.    TTestEnum = (te0, te1, te2, te3, te4, te5, te6, te7, te8, te9, te10, te11, te12, te13, te14, te15,
  11.                 te16, te17, te18, te19, te20, te21, te22, te23, te24, te25, te26, te27, te28, te29, te30, te31);
  12.   TTestSet = set of TTestEnum;
  13.  
  14.   { TForm1 }
  15.   TForm1 = class(TForm)
  16.     Button1: TButton;
  17.     procedure Button1Click(Sender: TObject);
  18.   private
  19.  
  20.   public
  21.  
  22.   end;
  23.  
  24. procedure SwitchSet(var ASet; const AItem; AOn: Boolean);
  25.  
  26. var
  27.   Form1: TForm1;
  28.  
  29. implementation
  30.  
  31. procedure SwitchSet(var ASet; const AItem; AOn: Boolean);
  32. type
  33.   TDummyEnum =
  34.     (de0, de1, de2, de3, de4, de5, de6, de7, de8, de9, de10, de11, de12, de13, de14, de15,
  35.      de16, de17, de18, de19, de20, de21, de22, de23, de24, de25, de26, de27, de28, de29, de30, de31);
  36.   TDummySet = set of TDummyEnum;
  37. begin
  38.   if AOn
  39.     then include(TDummySet(ASet), TDummyEnum(AItem))
  40.     else exclude(TDummySet(ASet), TDummyEnum(AItem));
  41. end;
  42.  
  43. {$R *.lfm}
  44.  
  45. { TForm1 }
  46.  
  47. procedure TForm1.Button1Click(Sender: TObject);
  48. var aEnum: TTestEnum;
  49.     aSet: TTestSet;
  50. begin
  51.   aSet:=[];
  52.   for aEnum:=low(TTestEnum) to high(TTestEnum) do
  53.     begin
  54.       SwitchSet(aSet, aEnum, True);
  55.       writeln('IsThere T: ', ord(aEnum), ' ', boolToStr(aEnum in aSet, 'T', 'F'));
  56.       SwitchSet(aSet, aEnum, False);
  57.       writeln('IsThere F: ', ord(aEnum), ' ', boolToStr(aEnum in aSet, 'T', 'F'));
  58.     end;
  59. end;
  60.  
  61. end.
Just start a new project, put there one button and assign OnClick event.
All is in procedure SwitchSet.
I have no clue about endianess. It would be nice if something like this (endian safe) would be part of FPC.
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

Blaazen

  • Hero Member
  • *****
  • Posts: 3237
  • POKE 54296,15
    • Eye-Candy Controls
Re: Is there a conditional Set that uses a boolean in a single function call ?
« Reply #12 on: September 21, 2020, 08:12:36 pm »
Unfortunately this does not allow to pass a enum, it must be vatiable.
(i.e. SwitchSet(aSet, te1, True); does not work.)
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: Is there a conditional Set that uses a boolean in a single function call ?
« Reply #13 on: September 21, 2020, 08:27:51 pm »
I think there's a fundamental missing operation here, which is being able to multiply an arbitrary set by a boolean to give the potential of clearing it without having to use conditionals (i.e. interrupt the flow of control).

If that operation worked, then xor (symmetric difference) could be used to set/reset an element without having to mess around with casts and without interrupting execution flow.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Blaazen

  • Hero Member
  • *****
  • Posts: 3237
  • POKE 54296,15
    • Eye-Candy Controls
Re: Is there a conditional Set that uses a boolean in a single function call ?
« Reply #14 on: September 21, 2020, 08:52:07 pm »
BTW, why compiler 3.3.1 does not complain?
Code: Pascal  [Select][+][-]
  1.   procedure Any(const Anything);
  2.   procedure DoIt;
  3.   ...
  4. implementation
  5.  
  6. procedure Any(const Anything);
  7. begin
  8.  
  9. end;
  10.  
  11. procedure DoIt;
  12. begin
  13.   Any([fsItalic, fsBold]);  //unit1.pas(31,25) Error: Variable identifier expected
  14.   Any(Cardinal([fsItalic, fsBold]));  //ok
  15. end;
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

 

TinyPortal © 2005-2018