Recent

Author Topic: Enum next element  (Read 3102 times)

tr_escape

  • Sr. Member
  • ****
  • Posts: 424
  • sector name toys | respect to spectre
    • Github:
Enum next element
« on: July 27, 2018, 02:47:14 pm »
Hello,

I just playing about enum types but I have a question:

I have got some numbers 10,20,30,40 in the type and I would like to get the next element of the enum, I tried for loop but I am getting whole numbers between 10 .. 40 but I would like get only 10,20,30 and 40.

Is there any suggestion?

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls
  9.  
  10.   ,typinfo
  11.  
  12.   ;
  13.  
  14. type
  15.   T_UnOrdered=(
  16.     element1 = (10),
  17.     element2 = (20),
  18.     element3 = (30),
  19.     element4 = (40)
  20.   );
  21.  
  22. type
  23.  
  24.   { TForm1 }
  25.  
  26.   TForm1 = class(TForm)
  27.     Button1: TButton;
  28.     Memo1: TMemo;
  29.     procedure Button1Click(Sender: TObject);
  30.   private
  31.  
  32.   public
  33.  
  34.   end;
  35.  
  36. var
  37.   Form1: TForm1;
  38.   Unordered : T_UnOrdered;
  39. implementation
  40.  
  41. {$R *.lfm}
  42.  
  43. { TForm1 }
  44.  
  45. procedure TForm1.Button1Click(Sender: TObject);
  46. var
  47.   n:T_UnOrdered;
  48. begin
  49.   Memo1.Lines.Clear;
  50.   for n:=Low( Unordered ) to High(Unordered) do
  51.     begin
  52.       // Memo1.Lines.Add(GetEnumName(Pointer(Unordered),Ord(n)));
  53.       Memo1.Lines.Add(IntToStr(Ord(n)));    // -->  10,11,12,13 ..... 40
  54.     end;
  55. end;
  56.  
  57. end.
  58.  

tudi_x

  • Hero Member
  • *****
  • Posts: 531
Re: Enum next element
« Reply #1 on: July 27, 2018, 03:02:00 pm »
hi,
did you check last section in:
http://wiki.lazarus.freepascal.org/Enumerated_types ?
Lazarus 2.0.2 64b on Debian LXDE 10

howardpc

  • Hero Member
  • *****
  • Posts: 4117
Re: Enum next element
« Reply #2 on: July 27, 2018, 03:22:59 pm »
AFAIK this is the only way to do such a thing:
Code: Pascal  [Select][+][-]
  1. program project1;
  2.  
  3. {$Mode objfpc}{$H+}
  4.  
  5. type
  6.   TDisjointed = (dj1=3, dj2=7, dj3=12, dj4=97);
  7.  
  8. var
  9.   dj: TDisjointed;
  10.   s: String;
  11.  
  12. begin
  13.   {$IOChecks OFF}
  14.   for dj := Low(TDisjointed) to High(TDisjointed) do
  15.     begin
  16.       WriteStr(s, dj);
  17.       if IOResult = 107 then
  18.         Continue;
  19.       WriteLn(s, '=', Ord(dj));
  20.     end;
  21.   ReadLn;
  22. end.

Thaddy

  • Hero Member
  • *****
  • Posts: 12898
Re: Enum next element
« Reply #3 on: July 27, 2018, 04:21:05 pm »
AFAIK this is the only way to do such a thing:
That is correct. Although I filed a request to improve this. Currently for some reason the loop runs over the range (low() to High() including the un-named values, not the actual named enum values.
You corrected this with continue, but there is no reason from a language point of view to improve it such that only the named items are looped.
The current status is bug prone, see the IOResult 107. Also the in operator does not work properly because of that. But then again Delphi has the same error-prone behavior.
As per your example, this demonstrates the issue:
Code: Pascal  [Select][+][-]
  1. program project1;
  2. {$Mode objfpc}{$H+}
  3. type
  4.   TDisjointed = (dj1=3, dj2=7, dj3=12, dj4=97);
  5. var
  6.   dj: TDisjointed;
  7.   s: String;
  8.   i:integer = 0;
  9. begin
  10.   {$IOChecks OFF}
  11.   for dj:= Low(TDisjointed) to High(TDisjointed) do
  12.     begin
  13.       WriteStr(s, dj);
  14.       inc(i);
  15.       if IOResult = 107 then
  16.         Continue;
  17.       WriteLn(s, '=', Ord(dj),' loop count:',i-1);
  18.     end;
  19.   ReadLn;
  20. end.
As it stands that are a lot of wasted cycles. Better to map them to an array.
« Last Edit: July 27, 2018, 05:14:39 pm by Thaddy »
Who is responsable for that!! The caller or the callee.. Out! ya'll, NOW. In UTC time, please, so maybe Yesterday or tomorrow.

Blaazen

  • Hero Member
  • *****
  • Posts: 3152
  • POKE 54296,15
    • Eye-Candy Controls
Re: Enum next element
« Reply #4 on: July 27, 2018, 05:17:02 pm »
Workaround with set:
Code: Pascal  [Select][+][-]
  1. type
  2.    T_UnOrdered=(
  3.     element1 = (10),
  4.     element2 = (20),
  5.     element3 = (30),
  6.     element4 = (40)
  7.   );
  8.   T_SetUnOrd = set of T_UnOrdered;
  9.  
  10. { ... }
  11.  
  12. var aUnOrd: T_UnOrdered;
  13.     aSetUnOrd: T_SetUnOrd;
  14. begin
  15.   aSetUnOrd:=[element1, element2, element3, element4];
  16.   for aUnOrd in aSetUnOrd do
  17.     writeln('aUnOrd ', aUnOrd, ', ', ord(aUnOrd));
  18. end;
  19.  

EDIT: Output
Code: Pascal  [Select][+][-]
  1. aUnOrd element1, 10
  2. aUnOrd element2, 20
  3. aUnOrd element3, 30
  4. aUnOrd element4, 40
« Last Edit: July 27, 2018, 05:18:47 pm by Blaazen »
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/

howardpc

  • Hero Member
  • *****
  • Posts: 4117
Re: Enum next element
« Reply #5 on: July 27, 2018, 07:11:15 pm »
Blaazen's set workaround applies to common use cases, but is limited to elements with ordinal numbers of type Byte.

So this fails if any enumeration element has a value above 255.

Blaazen

  • Hero Member
  • *****
  • Posts: 3152
  • POKE 54296,15
    • Eye-Candy Controls
Re: Enum next element
« Reply #6 on: July 27, 2018, 07:17:59 pm »
So another workaroud with array:
Code: Pascal  [Select][+][-]
  1. type
  2.    T_UnOrdered=(
  3.     element1,
  4.     element2,
  5.     element3,
  6.     element4
  7.   );
  8. {...}
  9. var aUnOrd: T_UnOrdered;
  10. const aArray: array [T_UnOrdered] of Integer = (10, 20, 30, 40);
  11. begin
  12.   for aUnOrd in T_UnOrdered do
  13.     writeln('aUnOrd ', aUnOrd, ', ', aArray[aUnOrd]);
  14. 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/

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Enum next element
« Reply #7 on: July 27, 2018, 07:30:56 pm »
Just the idea:

FPC has a table that holds (value, name) for each element. Write(someElement) uses that table to get the name. FPC generates fpc_write_text_enum for that Write. If you follow fpc_write_text_enum you will see a call to fpc_shortstr_enum_intern which can give you a way to that table.

A patch is always welcome.  :D

taazz

  • Hero Member
  • *****
  • Posts: 5364
Re: Enum next element
« Reply #8 on: July 28, 2018, 12:55:47 am »
Just the idea:

FPC has a table that holds (value, name) for each element. Write(someElement) uses that table to get the name. FPC generates fpc_write_text_enum for that Write. If you follow fpc_write_text_enum you will see a call to fpc_shortstr_enum_intern which can give you a way to that table.

A patch is always welcome.  :D
interesting! I always thought that compiler will change those to the correct string at compile time, if this is true then it would be in the rtl's best interest to change the succ, pred functions to use those arrays as needed instead of complaining about numbered enums.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Enum next element
« Reply #9 on: July 28, 2018, 07:58:47 am »
I always thought that compiler will change those to the correct string at compile time

Not yet, although there was a nice discussion about introducing "Pure" functions and compile-time functions that might have this effect in some controlled cases.

if this is true then it would be in the rtl's best interest to change the succ, pred functions to use those arrays as needed instead of complaining about numbered enums.
Just look at the generated assembly file (using -al).

First table has the names (and min/max):
Code: Pascal  [Select][+][-]
  1. .section .data.n_RTTI_$P$PROJECT1_$$_T_UNORDERED,"d"
  2.         .balign 4
  3. .globl  RTTI_$P$PROJECT1_$$_T_UNORDERED
  4. RTTI_$P$PROJECT1_$$_T_UNORDERED:
  5.         .byte   3,11
  6.         .ascii  "T_UnOrdered"
  7.         .byte   5
  8.         .long   10,40,0
  9.         .byte   8
  10.         .ascii  "element1"
  11.         .byte   8
  12.         .ascii  "element2"
  13.         .byte   8
  14.         .ascii  "element3"
  15.         .byte   8
  16.         .ascii  "element4"
  17.         .byte   8
  18.         .ascii  "Project1"
  19.         .byte   0

Two tables to help change ord to name, and name to ord:
Code: Pascal  [Select][+][-]
  1. .section .data.n_RTTI_$P$PROJECT1_$$_T_UNORDERED_s2o,"d"
  2.         .balign 4
  3. .globl  RTTI_$P$PROJECT1_$$_T_UNORDERED_s2o
  4. RTTI_$P$PROJECT1_$$_T_UNORDERED_s2o:
  5.         .long   4,10
  6.         .long   RTTI_$P$PROJECT1_$$_T_UNORDERED+26
  7.         .long   20
  8.         .long   RTTI_$P$PROJECT1_$$_T_UNORDERED+35
  9.         .long   30
  10.         .long   RTTI_$P$PROJECT1_$$_T_UNORDERED+44
  11.         .long   40
  12.         .long   RTTI_$P$PROJECT1_$$_T_UNORDERED+53
  13.  
  14. .section .data.n_RTTI_$P$PROJECT1_$$_T_UNORDERED_o2s,"d"
  15.         .balign 4
  16. .globl  RTTI_$P$PROJECT1_$$_T_UNORDERED_o2s
  17. RTTI_$P$PROJECT1_$$_T_UNORDERED_o2s:
  18.         .long   1,4,10
  19.         .long   RTTI_$P$PROJECT1_$$_T_UNORDERED+26
  20.         .long   20
  21.         .long   RTTI_$P$PROJECT1_$$_T_UNORDERED+35
  22.         .long   30
  23.         .long   RTTI_$P$PROJECT1_$$_T_UNORDERED+44
  24.         .long   40
  25.         .long   RTTI_$P$PROJECT1_$$_T_UNORDERED+53

See the suffix? o2s and s2o.

taazz

  • Hero Member
  • *****
  • Posts: 5364
Re: Enum next element
« Reply #10 on: July 28, 2018, 08:26:09 am »
I always thought that compiler will change those to the correct string at compile time

Not yet, although there was a nice discussion about introducing "Pure" functions and compile-time functions that might have this effect in some controlled cases.
thanks link bookmarked for later.
if this is true then it would be in the rtl's best interest to change the succ, pred functions to use those arrays as needed instead of complaining about numbered enums.
Just look at the generated assembly file (using -al).
sorry no asm skills, not even read.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

 

TinyPortal © 2005-2018