Re: basic questions about enums and enum types
- Posted by _tom (admin) Dec 23, 2018
- 897 views
being lazy here... I will just paste what Pete Lomax has said for Phix
There are a few small differences between oE and Phix on this (will have to work up a comparison sometime.)
_tom
Enum
An enum declaration can be used to define automatically-incrementing constants. The default behaviour is for the first item to be 1 and each subsequent item incremented by 1. An explict value may be specified for any item. Enums may currrently only take integer values (see below). Such values must always be numeric literals, as opposed to expressions or other variables or constants. Subsequent values default to the previous value plus one, unless they too are assigned a default value.
enum ONE=1, TWO, THREE, ABC=10, DEF, XYZ -- ONE is 1, TWO is 2, THREE is 3 -- ABC is 10, DEF is 11, XYZ is 12
Note that C enums start at 0 by default, and you should remember to specify "=0" on the first element when (manually) translating C to Phix, unless of course the enum is just being used to guarantee uniqueness and as such the actual values do not really matter.
It is not a bad idea to always explicitly specify the starting value of an enum, even if it is 1, to avoid confusing anyone more accustomed to the way enums behave in some other programming language.
As with other declarations, enums can be terminated with a $ for ease of editing enum lists that change frequently during development.
enum YES, NO, -- MAYBE, -- EITHER, -- SOMETIMES, OFTEN, -- RARELY, $ <eucode>
You can also use $ to replicate the last value, eg
( =$ syntax is Phix only )
enum ONE,TWO,THREE,ALL=$ ?{ONE,TWO,THREE,ALL} -- {1,2,3,3} enum UN,UNO=$,DUO,TRE,TRES=$ ?{UN,UNO,DUO,TRE,TRES} -- {1,1,2,3,3}
Obviously attempts to use $ on the very first enum trigger a compilation error ("no prior value").
Sequences use integer indexes, but with enum you may write code like this:
enum X, Y sequence point = { 0,0 } point[X] = 3 point[Y] = 4
enum type
There is also a special form of enum, an enum type. This is a simple way to write a user-defined type based on the set of values in a specific enum group.
The type created this way can be used anywhere a normal user-defined type can be used.
enum type RGBA RED, GREEN, BLUE, ALPHA end type -- Only allow values of RED, GREEN, BLUE, or ALPHA as parameters function xyz(RGBA x, RGBA y) return end function
The above enum statement is in fact (apart from the parameter being named "i") equivalent to:
enum RED, GREEN, BLUE, ALPHA type RGBA(integer i) return find(i,{RED, GREEN, BLUE, ALPHA}) end type
You may have spotted that there is one significant difference concerning enum types. Normal type functions return either 1 or 0, whereas enum type functions return a positive integer index when the argument is a member, or 0 if not.
The value returned is the ordinal number of the member in the enum definition, regardless of what the member value is. Should two enums share the same value, they will share the same ordinal number. The ordinal numbers of enums surrounding these continue to increment as if every enum had a unique ordinal number, causing some numbers to be skipped. Lastly, although only applicable for enum type routines that are likely to be invoked more than 106 times, it would be remiss of me not to mention that the use of find in enum types may be slower than say i>=RED and i<=ALPHA, especially for enum types with several dozen or a few hundred or maybe even thousands of elements, however it is no big deal to replace such with a faster explicit type much as above, should that be a significant concern.
enum type color RED=4, GREEN=7, BLACK=1, BLUE=3 , PINK=10 end type ? color(RED) -- 1 ? color(GREEN) -- 2 ? color(BLACK) -- 3 ? color(BLUE) -- 4 ? color(PINK) -- 5 constant color_names = {"rouge", "vert", "noir", "bleu", "rose"} puts(1, color_names[color(BLUE)]) -- bleu
However if RED and BLACK were (for some unknown reason) given the same value:
enum type color RED, GREEN=7, BLACK=1, BLUE=3 , PINK=10 end type ? color(RED) -- 1 ? color(GREEN) -- 2 ? color(BLACK) -- 1 ? color(BLUE) -- 4 ? color(PINK) -- 5
Note that none of the enums have an ordinal number with a value of 3. This is simply skipped. Unless an enum member is being set to a specific value, it defaults to 1 more than the previous member.
This default increment can be overridden. The syntax is:
enum [type name] by DELTA member1, member2, ... ,memberN
where 'DELTA' is a literal number with an optional +, -, or * operator preceding it. Also, for the same reasons that floating point for loops are prohibited, phix only supports integer enums, and hence only integer deltas, and is unlikely to ever support "by /N".
enum by 2 A,B,C=6,D -- values are 1,3,6,8 enum by * 2 A,B,C,D,E -- values are 1,2,4,8,16
Should both be present, a "by amount" clause must follow rather than precede "type name".