Recent

Author Topic: Centralising code  (Read 1218 times)

Kaller

  • Jr. Member
  • **
  • Posts: 72
Centralising code
« on: September 20, 2023, 05:49:04 am »
Suppose I have a bunch of enumerated states that are basically bistates, like left/right, up/down/ top/bottom on/off etc. and instead of writing a bunch of flip functions can I re-use a single Flip() function that toggles a state so that if I Flip(on) I get off and if I flip(up) I get down? Will generics do that for me?

Fibonacci

  • Full Member
  • ***
  • Posts: 222
  • #PDK
Re: Centralising code
« Reply #1 on: September 20, 2023, 06:17:00 am »
If your enums have only 2 states, then they are 0 and 1, you can use something like this:

Code: Pascal  [Select][+][-]
  1. procedure flip(e: PInteger);
  2. begin
  3.   e^ := integer(not boolean(e^));
  4. end;

And use it like this:

Code: Pascal  [Select][+][-]
  1. flip(@yourswitch);

Kaller

  • Jr. Member
  • **
  • Posts: 72
Re: Centralising code
« Reply #2 on: September 20, 2023, 08:02:04 am »
That's pretty slick.
« Last Edit: September 20, 2023, 08:34:40 am by Kaller »

Fibonacci

  • Full Member
  • ***
  • Posts: 222
  • #PDK
Re: Centralising code
« Reply #3 on: September 20, 2023, 08:27:31 am »
That's pretty slick. So I could assign values and Bob's your uncle.
 type  direction = (up = 0, down = 1);

Code: Pascal  [Select][+][-]
  1. type
  2.   onoff     = (on, off);
  3.   updown    = (up, down);
  4.   leftright = (left, right);
  5.  
  6. procedure flip(e: PInteger);
  7. begin
  8.   e^ := integer(not boolean(e^));
  9. end;
  10.  
  11. var
  12.   switch: onoff = on; //initial "on"
  13.  
  14. begin
  15.   writeln('switch = ', switch);
  16.   flip(@switch); //off
  17.   writeln('switch = ', switch);
  18.   flip(@switch); //on
  19.   writeln('switch = ', switch);
  20.   flip(@switch); //off
  21.   writeln('switch = ', switch);
  22.  
  23.   readln;
  24. end.

Quote
switch = on
switch = off
switch = on
switch = off

TRon

  • Hero Member
  • *****
  • Posts: 1870
Re: Centralising code
« Reply #4 on: September 20, 2023, 08:37:58 am »
Will generics do that for me?
Dunno tbh.

I like the following a bit more but I don't believe generic type helpers are supported (or planned).

Code: Pascal  [Select][+][-]
  1. program test;
  2.  
  3. {$mode objfpc}{$H+}
  4. {$modeswitch typehelpers}
  5.  
  6. type
  7.   THorDir = (hdLeft, hdRight);
  8.  
  9.   THorDirHelper = type helper for THorDir
  10.     procedure Flip;
  11.   end;
  12.  
  13. procedure THorDirHelper.Flip;
  14. begin
  15.   case ord(Self) of
  16.     0 : Ord(Self) := 1;
  17.     1 : Ord(Self) := 0;
  18.   end;
  19. end;
  20.  
  21. var
  22.   Horizontal: THorDir;
  23.  
  24. begin
  25.   Horizontal := hdLeft;
  26.   writeln('Horizontal = ', Horizontal);
  27.   Horizontal.Flip;
  28.   writeln('Horizontal = ', Horizontal);
  29.   Horizontal.Flip;
  30.   writeln('Horizontal = ', Horizontal);
  31. end.
  32.  
And ofc you can use Fibonacci's flip implementation code as well I just fancied mine  :).

Leledumbo

  • Hero Member
  • *****
  • Posts: 8718
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: Centralising code
« Reply #5 on: September 20, 2023, 08:38:06 am »
Pointer-free usage solution:
Code: Pascal  [Select][+][-]
  1. type
  2.   onoff     = (on, off);
  3.   updown    = (up, down);
  4.   leftright = (left, right);
  5.  
  6. procedure flip(var e); inline; // no actual function call needed
  7. begin
  8.   PBoolean(@e)^ := not Boolean(e);
  9. end;
  10.  
  11. var
  12.   switch: onoff = on; //initial "on"
  13.  
  14. begin
  15.   writeln('switch = ', switch);
  16.   flip(switch); //off
  17.   writeln('switch = ', switch);
  18.   flip(switch); //on
  19.   writeln('switch = ', switch);
  20.   flip(switch); //off
  21.   writeln('switch = ', switch);
  22.  
  23.   readln;
  24. end.
  25.  
« Last Edit: September 20, 2023, 08:51:41 am by Leledumbo »

Kaller

  • Jr. Member
  • **
  • Posts: 72
Re: Centralising code
« Reply #6 on: September 20, 2023, 08:43:18 am »
Not often you can solve something with one line of code. I am glad I asked the question.  It makes the code more readable using enum types instead of using clunky booleans, and so things like flip are just pretty.

alpine

  • Hero Member
  • *****
  • Posts: 891
Re: Centralising code
« Reply #7 on: September 20, 2023, 10:37:09 am »
Will generics do that for me?

Code: Pascal  [Select][+][-]
  1. type
  2.   TBistate = (One, Two);
  3.  
  4. generic procedure Flip<T>(var A: T);
  5. begin
  6.   A := T(Integer(A) xor 1);
  7. end;
  8.  
  9. var
  10.   Bi: TBistate;
  11.  
  12. begin
  13.   Bi := One; WriteLn(Bi);
  14.   specialize Flip<TBistate>(Bi); WriteLn(Bi);
  15.   specialize Flip<TBistate>(Bi); WriteLn(Bi);
  16. end.  
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9385
  • Debugger - SynEdit - and more
    • wiki
Re: Centralising code
« Reply #8 on: September 20, 2023, 12:42:32 pm »
If you have 2 "TMyEnum = (e1, e2)" values you can refer to them as "low(TMyEnum)" and "high(TMyEnum).


Warfley

  • Hero Member
  • *****
  • Posts: 1469
Re: Centralising code
« Reply #9 on: September 20, 2023, 03:46:15 pm »
As I'm currently on my phone, I can't test this, but I think that because they are based on pointers (which also using the var parameter implicitly is), neither of those approaches are actually generalizable to bitfields, so when accessing the members of a bit packed record probably all of these methods would fail, as bits are not pointer addressable.

Also the proposals so far assume a certain layout for enema, which may also not be applicable. Eg.g the enum
Code: Pascal  [Select][+][-]
  1. TTest = (testA=1, testB=1023)
Is neither binary not of each other nor xor 1.

A solution that's always applicable would be something using a function result and high and low
Code: Pascal  [Select][+][-]
  1. function Flip<T>(curr: T): T
  2. begin
  3.   If Curr = Low(T) then
  4.     Result:=high(T)
  5.   else if Curr=high(T) then
  6.     Result:=low(T)
  7.   Else
  8.     Raise Exception.Create('unknown enum state)
  9. end;

Kaller

  • Jr. Member
  • **
  • Posts: 72
Re: Centralising code
« Reply #10 on: September 21, 2023, 08:54:27 am »
That's a good one, and your phone converted enum to enema which is definitely not applicable  :D

Kays

  • Hero Member
  • *****
  • Posts: 546
  • Whasup!?
    • KaiBurghardt.de
Re: Centralizing code
« Reply #11 on: September 21, 2023, 11:58:47 am »
Suppose I have a bunch of enumerated states that are basically bistates, like left/right, up/down/ top/bottom on/off etc. and instead of writing a bunch of flip functions can I re-use a single Flip() function that toggles a state so that if I Flip(on) I get off and if I flip(up) I get down? Will generics do that for me?
What’s wrong with sets? There is no need to wrap this functionality into a function. A simple expression suffices:
Code: Pascal  [Select][+][-]
  1. program setBasedSwitchDemo(input, output, stdErr);
  2.         type
  3.                 bistate = (on);
  4.         var
  5.                 M: set of bistate;
  6.         begin
  7.                 M := []; { Represents “off” }
  8.                 M := M >< [on]; { A “flip”. }
  9.         end.
Yours Sincerely
Kai Burghardt

vangli

  • New Member
  • *
  • Posts: 42
Re: Centralising code
« Reply #12 on: September 21, 2023, 12:58:06 pm »
Regards Bent

 

TinyPortal © 2005-2018