### Bookstore

 Computer Math and Games in Pascal (preview) Lazarus Handbook

### Author Topic: Centralising code  (Read 1220 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.
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.
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

• Hero Member
• Posts: 9387
• Debugger - SynEdit - and more
##### 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

#### Kays

• Hero Member
• Posts: 546
• Whasup!?
##### 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