\chapter{Related Work}
\label{s:RelatedWork}

Enumeration-like features exist in many popular programming languages, both past and present, \eg Pascal~\cite{Pascal}, Ada~\cite{Ada}, \Csharp~\cite{Csharp}, OCaml~\cite{OCaml} \CC, Go~\cite{Go}, Haskell~\cite{Haskell} \see{discussion in \VRef{s:AlgebraicDataType}}, Java~\cite{Java}, Rust~\cite{Rust}, Swift~\cite{Swift}, Python~\cite{Python}.
Among these languages, there is a large set of overlapping features, but each language has its own unique extensions and restrictions.


\section{Pascal}
\label{s:Pascal}

Pascal introduced the \lstinline[language=Pascal]{const} aliasing declaration binding a name to a constant literal/expression.
\begin{pascal}
const Three = 2 + 1;   NULL = NIL;   PI = 3.14159;   Plus = '+';   Fred = 'Fred';
\end{pascal}
As stated, this mechanism is not an enumeration because there is no specific type (pseudo enumeration).
Hence, there is no notion of a (possibly ordered) set.
The type of each constant name (enumerator) is inferred from the constant-expression type.

Pascal introduced the enumeration type characterized by a set of ordered, unscoped identifiers (enumerators), which are not overloadable.\footnote{%
Pascal is \emph{case-insensitive} so identifiers may appear in multiple forms and still be the same, \eg \lstinline{Mon}, \lstinline{moN}, and \lstinline{MON} (a questionable design decision).}
\begin{pascal}
type Week = ( Mon, Tue, Wed, Thu, Fri, Sat, Sun );
\end{pascal}
Object initialization and assignment are restricted to the enumerators of this type.
Enumerators are auto-initialized from left to right, starting at zero and incrementing by 1.
Enumerators \emph{cannot} be explicitly initialized.
Pascal provides a predefined type \lstinline[language=Pascal]{Boolean} defined as:
\begin{pascal}
type Boolean = ( false, true );
\end{pascal}
The enumeration supports the relational operators @=@, @<>@, @<@, @<=@, @>=@, and @>@, interpreted as as comparison in terms of declaration order.

The following auto-generated pseudo-functions exist for all enumeration types:
\begin{cquote}
\begin{tabular}{@{}ll@{}}
@succ( T )@	& @succ( Tue ) = Wed@ \\
@pred( T )@	& @pred( Tue ) =  Mon@ \\
@ord( T )@	& @ord( Tue ) = 1@
\end{tabular}
\end{cquote}

Pascal provides \emph{consecutive} subsetting of an enumeration using a subrange type.
\begin{pascal}
type Week = ( Mon, Tue, Wed, Thu, Fri, Sat, Sun );
	   Weekday = @Mon..Fri@;   { subtype }
	   Weekend = @Sat..Sun@;
var day : Week;
	 wday : Weekday;
	 wend : Weekend;
\end{pascal}
Hence, declaration order of enumerators is crucial to provide the necessary ranges.
There is a bidirectional assignment between the enumeration and its subranges.
\begin{pascal}
day := Sat;
@wday := day;@			$\C[1.5in]{\{ check \}}$
wend := day;			$\C{\{ maybe check \}}$
day := Mon;
wday := day;			$\C{\{ maybe check \}}$
@wend := day;@			$\C{\{ check \}}$
day := wday;			$\C{\{ no check \}}$
day := wend;			$\C{\{ no check \}}\CRT$
\end{pascal}
A static/dynamic range check should be performed to verify the values assigned to subtypes.
(Free Pascal does not check and aborts in certain situations, like writing an invalid enumerator.)

An enumeration can be used in the @if@ and @case@ statements or iterating constructs.
\begin{cquote}
\setlength{\tabcolsep}{15pt}
\begin{tabular}{@{}ll@{}}
\begin{pascal}
day := Mon;
if @day@ = wday then
	Writeln( day );
if @day@ <= Fri then
	Writeln( 'weekday');
Mon
weekday
\end{pascal}
&
\begin{pascal}

case @day@ of
  Mon..Fri :
	Writeln( 'weekday');
  Sat..Sun :
	Writeln( 'weekend')
end;
weekday
\end{pascal}
\end{tabular}
\end{cquote}
\begin{cquote}
\setlength{\tabcolsep}{15pt}
\begin{tabular}{@{}ll@{}}
\begin{pascal}
while day <= Sun do begin
	Write( day, ' ' );
	day := succ( day );
end;
Mon Tue Wed Thu Fri Sat Sun 
\end{pascal}
&
\begin{pascal}
for day := Mon to Sun do begin
	Write( day, ' ' );

end;
Mon Tue Wed Thu Fri Sat Sun 
\end{pascal}
\end{tabular}
\end{cquote}
Note that subtypes @Weekday@ and @Weekend@ cannot be used to define a case or loop range.

An enumeration type can be used as an array dimension and subscript.
\begin{pascal}
Lunch : array( @Week@ ) of Time;
for day in Week loop
	Lunch( @day@ ) := ... ;       { set lunch time }
end loop;
\end{pascal}

Free Pascal~\cite[\S~3.1.1]{FreePascal} is a modern, object-oriented version of Pascal, with a C-style enumeration type.
Enumerators can be assigned explicit values assigned in ascending numerical order using a constant expression, and the range can be non-consecutive.
\begin{pascal}
type Count = ( Zero, One, Two, Ten = 10, Eleven );
\end{pascal}
Pseudo-functions @pred@ and @succ@ can only be used if the range is consecutive.
Enumerating gives extraneous values.
\begin{pascal}
for cnt := Zero to Eleven do begin
	Write( ord( cnt ), ' ' );
end;
0 1 2 @3 4 5 6 7 8 9@ 10 11 
\end{pascal}

The underlying type is an implementation-defined integral type large enough to hold all enumerated values; it does not have to be the smallest possible type.
The integral size can be explicitly specified using compiler directive \$@PACKENUM@~$N$, where $N$ is the number of bytes, \eg:
\begin{pascal}
Type @{$\color{red}\$$PACKENUM 1}@ SmallEnum = ( one, two, three );
		@{$\color{red}\$$PACKENUM 4}@ LargeEnum = ( BigOne, BigTwo, BigThree );
Var S : SmallEnum; { 1 byte }
	  L : LargeEnum; { 4 bytes}
\end{pascal}


\section{Ada}
\label{s:Ada}

An Ada enumeration type is a set of ordered, unscoped identifiers (enumerators) bound to \emph{unique} \newterm{literals}.\footnote{%
Ada is \emph{case-insensitive} so identifiers may appear in multiple forms and still be the same, \eg \lstinline{Mon}, \lstinline{moN}, and \lstinline{MON} (a questionable design decision).}
\begin{ada}
type Week is ( Mon, Tue, Wed, Thu, Fri, Sat, Sun ); -- literals (enumerators)
\end{ada}
Object initialization and assignment are restricted to the enumerators of this type.
While Ada enumerators are unscoped, like C, Ada enumerators are overloadable.
\begin{ada}
type RGB is ( @Red@, @Green@, Blue );
type Traffic_Light is ( @Red@, Yellow, @Green@ );
\end{ada}
Like \CFA, Ada uses a type-resolution algorithm, including the left-hand side of the assignment, to disambiguate among overloaded identifiers.
\VRef[Figure]{f:AdaEnumeration} shows how ambiguity is handled using a cast, \eg \lstinline[language=ada]{RGB'(Red)}.

\begin{figure}
\begin{ada}
with Ada.Text_IO; use Ada.Text_IO;
procedure test is
	type RGB is ( @Red@, Green, Blue );
	type Traffic_Light is ( @Red@, Yellow, Green );         -- overload
	procedure @Red@( Colour : RGB ) is begin            -- overload
		Put_Line( "Colour is " & RGB'Image( Colour ) );
	end Red;
	procedure @Red@( TL : Traffic_Light ) is begin       -- overload
		Put_Line( "Light is " & Traffic_Light'Image( TL ) );
	end Red;
begin
	@Red@( Blue );				 -- RGB
	@Red@( Yellow );				-- Traffic_Light
	@Red@( @RGB'(Red)@ );		-- ambiguous without cast
end test;
\end{ada}
\caption{Ada Enumeration Overload Resolution} 
\label{f:AdaEnumeration}
\end{figure}

Enumerators without initialization are auto-initialized from left to right, starting at zero and incrementing by 1.
Enumerators with initialization must set \emph{all} enumerators in \emph{ascending} order, \ie there is no auto-initialization.
\begin{ada}
type Week is ( Mon, Tue, Wed, Thu, Fri, Sat, Sun );
	for Week use ( Mon => 0, Tue => 1, Wed => 2, Thu => @10@, Fri => 11, Sat => 14, Sun => 15 );
\end{ada}
The enumeration operators are the equality and relational operators, @=@, @/=@, @<@, @<=@, @=@, @/=@, @>=@, @>@, where the ordering relationship is given implicitly by the sequence of ascending enumerators.

Ada provides an alias mechanism, \lstinline[language=ada]{renames}, for aliasing types, which is useful to shorten package identifiers.
\begin{ada}
@OtherRed@ : RGB renames Red;
\end{ada}
which suggests a possible \CFA extension to @typedef@.
\begin{cfa}
typedef RGB.Red OtherRed;
\end{cfa}

There are three pairs of inverse enumeration pseudo-functions (attributes): @'Pos@ and @'Val@, @'Enum_Rep@ and @'Enum_Val@, and @'Image@ and @'Value@,
\begin{cquote}
\setlength{\tabcolsep}{15pt}
\begin{tabular}{@{}ll@{}}
\begin{ada}
RGB'Pos( Red ) = 0;
RGB'Enum_Rep( Red ) = 10;
RGB'Image( Red ) = "RED";
\end{ada}
&
\begin{ada}
RGB'Val( 0 ) = Red
RGB'Enum_Val( 10 ) =  Red
RGB'Value( "Red" ) =  Red
\end{ada}
\end{tabular}
\end{cquote}
These attributes are important for IO.
An enumeration type @T@ also has the following attributes: @T'First@, @T'Last@, @T'Range@, @T'Pred@, @T'Succ@, @T'Min@, and @T'Max@, producing an intuitive result based on the attribute name.

Ada allows the enumerator label to be a character constant.
\begin{ada}
type Operator is ( '+', '-', '*', '/' );
\end{ada}
which is syntactic sugar for the label and not character literals from the predefined type @Character@.
The purpose is strictly readability using character literals rather than identifiers.
\begin{ada}
Op : Operator := '+';
if Op = '+' or else Op = '-' then ... ;
elsif Op = '*' or else Op = '/' then ... ; end if;
\end{ada}
Interestingly, arrays of character enumerators can be treated as strings.
\begin{ada}
Ops : array( 0..3 ) of Operator;
Ops := @"+-*/"@;            -- string assignment to array elements
Ops := "+-" @&@ "*/";   -- string concatenation and assignment
\end{ada}
Ada's @Character@ type is defined as a character enumeration across all Latin-1 characters.

Ada's boolean type is also a special enumeration, which can be used in conditions.
\begin{ada}
type Boolean is (False, True); -- False / True not keywords
@Flag@ : Boolean;
if @Flag@ then ...    -- conditional
\end{ada}
Since only types derived from @Boolean@ can be conditional, @Boolean@ is essentially a builtin type.

Ada provides \emph{consecutive} subsetting of an enumeration using \lstinline[language=ada]{range}.
\begin{ada}
type Week is ( Mon, Tue, Wed, Thu, Fri, Sat, Sun );
subtype Weekday is Week @range Mon .. Fri@;
subtype Weekend is Week @range Sat .. Sun@;
Day : Week;
\end{ada}
Hence, the ordering of the enumerators is crucial to provide the necessary ranges.

An enumeration type can be used in the Ada \lstinline[language=ada]{case} (all enumerators must appear or a @default@) or iterating constructs.
\begin{cquote}
\setlength{\tabcolsep}{15pt}
\begin{tabular}{@{}ll@{}}
\begin{ada}
case Day is
	when @Mon .. Fri@ => ... ;
	when @Sat .. Sun@ => ... ;
end case;
\end{ada}
&
\begin{ada}
case Day is
	when @Weekday@ => ... ;  -- subtype ranges
	when @Weekend@ => ... ;
end case;
\end{ada}
\end{tabular}
\end{cquote}

\begin{cquote}
\setlength{\tabcolsep}{12pt}
\begin{tabular}{@{}lll@{}}
\begin{ada}
for Day in @Mon .. Sun@ loop
	...
end loop;
\end{ada}
&
\begin{ada}
for Day in @Weekday@ loop
	...
end loop;
\end{ada}
&
\begin{ada}
for Day in @Weekend@ loop
	...
end loop;
\end{ada}
\end{tabular}
\end{cquote}

An enumeration type can be used as an array dimension and subscript.
\begin{ada}
Lunch : array( @Week@ ) of Time;
for Day in Week loop
	Lunch( @Day@ ) := ... ;       -- set lunch time
end loop;
\end{ada}


\section{\CC}
\label{s:C++RelatedWork}

\CC enumeration is largely backward compatible with C, so it inherited C's enumerations with some modifications and additions.

\CC has aliasing using @const@ declarations, like C \see{\VRef{s:Cconst}}, with type inferencing, plus static/dynamic initialization.
(Note, a \CC @constexpr@ declaration is the same as @const@ with the restriction that the initialization is a compile-time expression.)
\begin{c++}
const @auto@ one = 0 + 1;				$\C{// static initialization}$
const @auto@ NIL = nullptr;
const @auto@ PI = 3.14159;
const @auto@ Plus = '+';
const @auto@ Fred = "Fred";
const @auto@ Mon = 0, Tue = Mon + 1, Wed = Tue + 1, Thu = Wed + 1, Fri = Thu + 1,
				Sat = Fri + 1, Sun = Sat + 1;
void foo() {
	const @auto@ r = random();			$\C{// dynamic initialization}$
	int va[r];							$\C{// VLA, auto scope only}$
}
\end{c++}
Statically initialized identifiers may appear in any constant-expression context, \eg @case@.
Dynamically initialized identifiers may appear as array dimensions in @g++@, which allows variable-sized arrays.
Interestingly, global \CC @const@ declarations are implicitly marked @static@ (@r@, read-only local, rather than @R@, read-only external)
\begin{c++}
$\$$ nm test.o
0000000000000018 @r@ Mon
\end{c++}
whereas C @const@ declarations without @static@ are marked @R@.
This difference results from linking concerns that come from templates.

The following \CC non-backward compatible change is made, plus the safe-assignment change shown in~\VRef{s:TypeSafety}.
\begin{cquote}
\begin{description}[leftmargin=*,topsep=0pt,itemsep=0pt,parsep=0pt]
\item[Change:] In \CC, the type of an enumerator is its enumeration.
In C, the type of an enumerator is @int@.
Example:
\begin{c++}
enum e { A };
sizeof(A) == sizeof(int)		 		$\C{// in C}$
sizeof(A) == sizeof(e)		 			$\C{// in \CC}$
/* and sizeof(int) is not necessary equal to sizeof(e) */
\end{c++}
\item[Rationale:] In \CC, an enumeration is a distinct type.
\item[Effect on original feature:] Change to semantics of well-defined feature.
\item[Difficulty of converting:] Semantic transformation.
\item[How widely used:] Seldom. The only time this affects existing C code is when the size of an enumerator is taken.
Taking the size of an enumerator is not a common C coding practice.
\end{description}
\hfill ISO/IEC 14882:1998 (\CC Programming Language Standard)~\cite[C.1.5.7.2.6]{ANSI98:C++}
\end{cquote}
Hence, the values in a \CC enumeration can only be its enumerators (without a cast).

While the storage size of an enumerator is up to the compiler, there is still an implicit cast to @int@.
\begin{c++}
enum E { A, B, C };
E e = A;
int i = A;    i = e; 					$\C{// implicit casts to int}$
\end{c++}
\CC{11} added a scoped enumeration, \lstinline[language=c++]{enum class} (or \lstinline[language=c++]{enum struct})\footnote{
The use of keyword \lstinline[language=c++]{class} is reasonable because default visibility is \lstinline[language=c++]{private} (scoped).
However, default visibility for \lstinline[language=c++]{struct} is \lstinline[language=c++]{public} (unscoped) making it an odd choice.},
where the enumerators are accessed using type qualification.
\begin{c++}
enum class E { A, B, C };
E e = @E::@A;	 						$\C{// qualified enumerator}$
e = B;	 								$\C{// error: B not in scope}$
\end{c++}
\CC{20} supports explicit unscoping with a \lstinline[language=c++]{using enum} declaration.
\begin{c++}
enum class E { A, B, C };
@using enum E;@
E e = A;    e = B;						$\C{// direct access}$
\end{c++}
\CC{11} added the ability to explicitly declare an underlying \emph{integral} type for \lstinline[language=c++]{enum class}.
\begin{c++}
enum class RGB @: long@ { Red, Green, Blue };
enum class rgb @: char@ { Red = 'r', Green = 'g', Blue = 'b' };
enum class srgb @: signed char@ { Red = -1, Green = 0, Blue = 1 };
\end{c++}
There is no implicit conversion from the \lstinline[language=c++]{enum class} type to its declared type.
\begin{c++}
rgb crgb = rgb::Red;
char ch = rgb::Red;   ch = crgb;		$\C{// error}$
\end{c++}
An enumeration can be used in the @if@ and @switch@ statements.
\begin{cquote}
\setlength{\tabcolsep}{15pt}
\begin{tabular}{@{}ll@{}}
\begin{c++}
if ( @day@ <= Fri )
	cout << "weekday" << endl;




\end{c++}
&
\begin{c++}
switch ( @day@ ) {
  case Mon: case Tue: case Wed: case Thu: case Fri:
	cout << "weekday" << endl; break;
  case Sat: case Sun:
	cout << "weekend" << endl; break;
}
\end{c++}
\end{tabular}
\end{cquote}
However, there is no mechanism to iterate through an enumeration.
A common workaround is to iterate over enumerator as integral values, but it only works if 
enumerators resemble a sequence of natural, i.e., enumerators are auto-initialized.
Otherwise, the iteration would have integers that are not enumeration values.
\begin{c++}
enum Week { Mon, Tue, Wed, Thu = 10, Fri, Sat, Sun };
for ( Week d = Mon; d <= Sun; d = @(Week)(d + 1)@ ) cout << d << ' ';
0 1 2 @3 4 5 6 7 8 9@ 10 11 12 13
\end{c++}
As a consequence, there is no meaningful enumerating mechanism.

An enumeration type cannot declare an array dimension but an enumerator can be used as a subscript.
There is no mechanism to subset or inherit from an enumeration.


\section{C\texorpdfstring{\raisebox{-0.7ex}{\LARGE$^\sharp$}\xspace}{Csharp}} % latex bug: cannot use \relsize{2} so use \LARGE
\label{s:Csharp}

% https://www.tutorialsteacher.com/codeeditor?cid=cs-mk8Ojx
% https://learn.microsoft.com/en-us/dotnet/api/system.enum?view=net-8.0
% https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/enums

\Csharp is a programming language with a scoped, integral enumeration similar to \CC \lstinline[language=C++]{enum class}.
\begin{csharp}
enum Week : @long@ { Mon, Tue, Wed, Thu@ = 10@, Fri, Sat, Sun }
enum RGB { Red, Green, Blue }
\end{csharp}
The default underlying integral type is @int@, with auto-incrementing and implicit/explicit initialization.
A method cannot be defined in an enumeration type (extension methods are possible).
There is an explicit bidirectional conversion between an enumeration and its integral type, and an implicit conversion to the enumerator label in display contexts.
\begin{csharp}
int iday = (int)Week.Fri;			$\C{// day == 11}$
Week day = @(Week)@42;				$\C{// day == 42, unsafe}$
string mon = Week.Mon.ToString();	$\C{// mon == "Mon"}$
RGB rgb = RGB.Red;					$\C{// rgb == "Red"}$
day = @(Week)@rgb;					$\C{// day == "Mon", unsafe}$
Console.WriteLine( Week.Fri );		$\C{// print label Fri}$
\end{csharp}
% The majority of the integral operators (relational and arithmetic) work with enumerations, except @*@ and @/@.
% Relational and arithmetic operators are defined in terms of its numeric value only. 
% Therefore, enumerators are not ordered and not enumerable like \CC.
Like \CC, \Csharp defines enumeration relational and arithmetic operators in terms of value.
Enumerators have no defined positional meaning.
\begin{csharp}
day = day++ - 5;					$\C{// value manipulation}$
day = day & day;
\end{csharp}
\begin{csharp}
for ( Week d = Mon; d <= Sun; @d += 1@ ) {
	Console.Write( d + " " );
}
Mon Tue Wed @3 4 5 6 7 8 9@ Thu Fri Sat Sun
\end{csharp}
As a consequence, there is no direct meaningful enumerating mechanism. 

An enumeration can be used in the @if@ and @switch@ statements.
\begin{cquote}
\setlength{\tabcolsep}{15pt}
\begin{tabular}{@{}ll@{}}
\begin{csharp}
if ( @day@ <= Week.Fri )
	Console.WriteLine( "weekday" );





\end{csharp}
&
\begin{csharp}
switch ( @day@ ) {
  case Week.Mon: case Week.Tue: case Week.Wed:
  case Week.Thu: case Week.Fri:
	Console.WriteLine( "weekday" ); break;
  case Week.Sat: case Week.Sun:
	Console.WriteLine( "weekend" ); break;
}
\end{csharp}
\end{tabular}
\end{cquote}

To indirectly enumerate, \Csharp's Enum library provides @Enum.GetValues@, 
a static member of abstract Enum type that return a reference to an array of all enumeration constants.
Internally, an Enum type has a static member called @fieldInfoHash@ -- a @Hashtable@ that stores information about enumerators.
The field is populated on-demand: it only contains information if a @reflection@ like @GetValues@ is called.
As an optimization, this information is cached, so the cost of reflection is paid once throughout the lifetime of a program.
@GetValues@ then converts a @Hashtable@ to an @Array@, which supports enumerating.
\begin{csharp}
foreach ( Week d in @Enum.GetValues@( typeof(Week) ) ) {
	Console.WriteLine( d + " " + (int)d + " " ); // label, position
}
Mon 0, Tue 1, Wed 2, Thu 10, Fri 11, Sat 12, Sun 13,
\end{csharp}
Hence, enumerating is not supplied directly by the enumeration, but indirectly through the expensive $O(N)$ creation of an enumerable array type, and recreating this array for each enumerating, versus direct arithmetic.

An enumeration type cannot declare an array dimension but an enumerator can be used as a subscript.
There is no mechanism to subset or inherit from an enumeration.

The @Flags@ attribute creates a bit-flags enumeration, making bitwise operators @&@, @|@, @~@ (complement), @^@ (xor) sensible.
\begin{csharp}
@[Flags]@ public enum Week {
	None = 0x0, Mon = 0x1, Tue = 0x2, Wed = 0x4,
	Thu = 0x8, Fri = 0x10, Sat = 0x20, Sun = 0x40,
	Weekdays = @Mon | Tue | Wed | Thu | Fri@ $\C{// Weekdays == 0x1f}$
	Weekend = @Sat | Sun@,			$\C{// Weekend == 0x60}$
}
Week meetings = @Week.Mon | Week.Wed@; $\C{// 0x5}$
\end{csharp}


\section{Go}
\label{s:Go}

Go has @const@ aliasing declarations, similar to \CC \see{\VRef{s:C++RelatedWork}}, for basic types with type inferencing and static initialization (constant expression).
The most basic form of constant definition is a @const@ keyword, followed by the name of constant, an optional type declaration of the constant, and a mandatory initialize.
For example:
\begin{Go}
const R @int@ = 0;  const G @uint@ = 1;  const B = 2; $\C{// explicit typing and type inferencing}$
const Fred = "Fred";  const Mary = "Mary";  const Jane = "Jane";
const S = 0;  const T = 0;
const USA = "USA";  const U = "USA";
const V = 3.1;  const W = 3.1;
\end{Go}
These declarations defined immutable and unscoped variables, and Go has no naming overloading. If no type declaration is provided, Go infers 
type from the initializer expression.

% Go provides an enumeration-like feature to group together @const@ declaration into a block and introduces a form of auto-initialization.
These named constants can be grouped together in one @const@ declaration block to introduce a form of auto-initialization.
\begin{Go}
const ( R = 0; G; B )					$\C{// implicit initialization: 0 0 0}$
const ( Fred = "Fred"; Mary = "Mary"; Jane = "Jane" ) $\C{// explicit initialization: Fred Mary Jane}$
const ( S = 0; T; USA = "USA"; U; V = 3.1; W ) $\C{// implicit/explicit: 0 0 USA USA 3.1 3.1}$
\end{Go}
The first identifier \emph{must} be explicitly initialized;
subsequent identifiers can be implicitly or explicitly initialized.
Implicit initialization always uses the \emph{previous} (predecessor) constant expression initializer.
A constant block can still use explicit declarations, and the following constants inherit that type.
\begin{Go}
type BigInt int64
const ( R @BigInt@ = 0; G; B )
const ( Fred @string@ = "Fred"; Mary = "Mary"; Jane = "Jane" )
const ( S @int@ = 0; T; USA @string@ = "USA"; U; V @float32@ = 3.1; W )
\end{Go}
Typing the first constant and implicit initializing is still not an enumeration because there is no unique type for the constant block;
nothing stops other constant blocks from being of the same type. 

Each @const@ declaration provides an implicit \emph{compile-time} integer counter starting at @0@, called \lstinline[language=Go]{iota}, which is post-incremented after each constant declaration.
% Each @const@ declaration is often paired with a const expression \lstinline[language=Go]{iota} to re-define its implicit initialization.
% \lstinline[language=Go]{iota} represents a sequence of natural numbers starting from zero.
% Using \lstinline[language=Go]{iota} outside of a @const@ block always sets the identifier to zero.
% \begin{Go}
% const R = iota;							$\C{// 0}$
% \end{Go}
% Inside a @const@ block, \lstinline[language=Go]{iota} is implicitly incremented for each \lstinline[language=golang]{const} identifier and used to initialize the next uninitialized identifier.
% Inside a @const@ block, if a constant has \lstinline[language=Go]{iota} initializer, its successor will also use \lstinline[language=Go]{iota} initializer.
% Inside a @const@ block, if a constant has \lstinline[language=Go]{iota} initializer, its successor will also use \lstinline[language=Go]{iota} initializer.
% \lstinline[language=Go]{iota} is no different than other constant expression when it is used in implicit initialization, but thanks to the increment natural of \lstinline[language=Go]{iota}, the successor will have a value equal to its predecessor plus 1.
\begin{Go}
const ( R = @iota@; G; B )					$\C{// implicit: 0 1 2}$
const ( C = @iota + B + 1@; G; Y )			$\C{// implicit: 3 4 5}$
\end{Go}
which are equivalent to:
\begin{Go}
const ( R = @iota@; G = @iota@; B = @iota@ ) $\C{// implicit: 0 1 2}$
const ( C = @iota + B + 1@; G = @iota + B + 1@; Y = @iota + B + 1@ ) $\C{// implicit: 3 4 5}$
\end{Go}
An underscore \lstinline[language=golang]{const} identifier advances \lstinline[language=Go]{iota}.
\begin{Go}
const ( O1 = iota + 1; @_@; O3; @_@; O5 )	$\C{// 1, 3, 5}$
\end{Go}
Auto-initialization reverts from \lstinline[language=Go]{iota} to the previous value after an explicit initialization, but auto-incrementing of \lstinline[language=Go]{iota} continues.
\begin{Go}
const ( Mon = iota; Tue; Wed;				$\C{// 0, 1, 2}$
		 @Thu = 10@; Fri; Sat; @Sun = iota@ ) $\C{// 10, 10, 10, {\color{red}6}}$
\end{Go}
Auto-initialization from \lstinline[language=Go]{iota} is restarted and \lstinline[language=Go]{iota} reinitialized with an expression containing at most \emph{one} \lstinline[language=Go]{iota}.
\begin{Go}
const ( V1 = iota; V2; @V3 = 7;@ V4 = @iota@ + 1; V5 ) // 0 1 7 4 5
const ( Mon = iota; Tue; Wed; // 0, 1, 2
		@Thu = 10;@ Fri = @iota@ - Wed + Thu - 1; Sat; Sun ) // 10, 11, 12, 13
\end{Go}
Here, @V4@ and @Fri@ restart auto-incrementing from \lstinline[language=Go]{iota} and reset \lstinline[language=Go]{iota} to 4 and 11, respectively, because of the initialization expressions containing \lstinline[language=Go]{iota}.
Note, because \lstinline[language=Go]{iota} is incremented for an explicitly initialized identifier or @_@,
at @Fri@ \lstinline[language=Go]{iota} is 4 requiring the minus one to compute the value for @Fri@.

Basic switch and looping are possible.
\begin{cquote}
\setlength{\tabcolsep}{20pt}
\begin{tabular}{@{}ll@{}}
\begin{Go}
day := Mon;	// := $\(\Rightarrow\)$ type inferencing
switch @day@ {
  case Mon, Tue, Wed, Thu, Fri:
	fmt.Println( "weekday" );
  case Sat, Sun:
	fmt.Println( "weekend" );
}
\end{Go}
&
\begin{Go}

for i := @Mon@; i <= @Sun@; i += 1 {
	fmt.Println( i )
}



\end{Go}
\end{tabular}
\end{cquote}
However, the loop in this example prints the values from 0 to 13 because there is no actual enumeration.

A constant variable can be used as an array dimension or a subscript.
\begin{Go}
var ar[@Sun@] int
ar[@Mon@] = 3
\end{Go}


\section{Java}

Java provides an enumeration using a specialized class.
A basic Java enumeration is an opaque enumeration, where the enumerators are constants.
\begin{Java}
enum Week { Mon, Tue, Wed, Thu, Fri, Sat, Sun; }
Week day = Week.Sat;
\end{Java}
The enumerator's members are scoped, requiring qualification.
The value of an enumeration instance is restricted to its enumerators.

The position (ordinal) and label (name) are accessible but there is no value property.
\begin{Java}
System.out.println( day.!ordinal()! + " " + !day! + " " + day.!name()! );
5 Sat Sat
\end{Java}
Since @day@ has no value, it prints its label (name).
The member @valueOf@ is the inverse of @name@ converting a string to an enumerator.
\begin{Java}
day = Week.valueOf( "Wed" );
\end{Java}
Extra members can be added to provide specialized operations.
\begin{Java}
public boolean isWeekday() { return !ordinal()! <= Fri.ordinal(); }
public boolean isWeekend() { return Sat.ordinal() <= !ordinal()!; }
\end{Java}
Notice the unqualified calls to @ordinal@ in the members implying a \lstinline[language=Java]{this} to some implicit implementation variable, likely an @int@.

Enumerator values require an enumeration type (any Java type may be used) and implementation member.
\begin{Java}
enum Week {
	Mon!(1)!, Tue!(2)!, Wed!(3)!, Thu!(4)!, Fri!(5)!, Sat!(6)!, Sun!(7)!; // must appear first
	private !long! day;					$\C{// enumeration type and implementation member}$
	private Week( !long! d ) { day = d; } $\C{// enumerator initialization}$
};
Week day = Week.Sat;
\end{Java}
The position, value, and label are accessible.
\begin{Java}
System.out.println( !day.ordinal()! + " " + !day.day! + " " + !day.name()! );
5 6 Sat
\end{Java}
If the implementation member is \lstinline[language=Java]{public}, the enumeration is unsafe, as any value of the underlying type can be assigned to it, \eg @day = 42@.
The implementation constructor must be private since it is only used internally to initialize the enumerators.
Initialization occurs at the enumeration-type declaration.

Enumerations can be used in the @if@ and @switch@ statements but only for equality tests.
\begin{cquote}
\setlength{\tabcolsep}{15pt}
\begin{tabular}{@{}ll@{}}
\begin{Java}
if ( !day! == Week.Fri )
	System.out.println( "Fri" );




\end{Java}
&
\begin{Java}
switch ( !day! ) {
  case Mon: case Tue: case Wed: case Thu: case Fri:
	System.out.println( "weekday" );  break;
  case Sat: case Sun:
	System.out.println( "weekend" );  break;
}
\end{Java}
\end{tabular}
\end{cquote}
Notice enumerators in the @switch@ statement do not require qualification.

There are no arithmetic operations on enumerations, so there is no arithmetic way to iterate through an enumeration without making the implementation type \lstinline[language=Java]{public}.
Like \Csharp, enumerating is supplied indirectly through another enumerable type, not via the enumeration.
Specifically, Java supplies a static method @values@, which returns an array of enumerator values.
Unfortunately, @values@ is an expensive @O(n)@ operation, which is recreated each time it is called. 
\begin{Java}
for ( Week d : Week.values() ) {
	System.out.print( d.ordinal() + d.day + " " +  d.name() + ",  " );
}
0 1 Mon,  1 2 Tue,  2 3 Wed,  3 4 Thu,  4 5 Fri,  5 6 Sat,  6 7 Sun,  
\end{Java}

% Java provides an @EnumSet@ where the underlying type is an efficient set of bits, one per enumeration \see{\Csharp \lstinline{Flags}, \VRef{s:Csharp}}, providing (logical) operations on groups of enumerators.
% There is also a specialized version of @HashMap@ with enumerator keys, which has performance benefits.
Java provides @EnumSet@, an auxiliary data structure that takes an enum @class@ as parameter (Week.class) for its construction, and it contains members only with the supplied enum type.
@EnumSet@ is enumerable because it extends @AbstractSet@ interfaces and thus supports direct enumerating via @forEach@.
It also has subset operation @range@ and it is possible to add to and remove from members of the set. 
@EnumSet@ supports more enumeration features, but it is not an enumeration type; it is a set of enumerators from a pre-defined enum. 

An enumeration type cannot declare an array dimension nor can an enumerator be used as a subscript.
Enumeration inheritence is disallowed because an enumeration is \lstinline[language=Java]{final}.


\section{Rust}

% https://doc.rust-lang.org/reference/items/enumerations.html

Rust @enum@ provides two largely independent mechanisms from a single language feature: an ADT and an enumeration.
When @enum@ is an ADT, pattern matching is used to discriminate among the variant types.
\begin{cquote}
\begin{tabular}{@{}l@{\hspace{30pt}}ll@{}}
\begin{rust}
struct S {
	i : isize,  j : isize
}
let mut s = S{ i : 3, j : 4 };
enum @ADT@ {
	I( isize ), $\C[1in]{// int}$
	F( f64 ),   $\C{// float}$
	S( S ),     $\C{// struct}\CRT$
}
\end{rust}
&
\begin{rust}
let mut adt : ADT;
adt = ADT::I(3);  println!( "{:?}", adt );
adt = ADT::F(3.5);  println!( "{:?}", adt );
adt = ADT::S(s);  println!( "{:?}", adt );
@match@ adt {
	ADT::I( i ) $=>$ println!( "{:}", i ),
	ADT::F( f ) $=>$ println!( "{:}", f ),
	ADT::S( s ) $=>$ println!( "{:} {:}", s.i, s.j ),
}
\end{rust}
&
\begin{rust}
I(3)
F(3.5)
S(S { i: 3, j: 4 })
3 4





\end{rust}
\end{tabular}
\end{cquote}
Even when the variant types are the unit type, the ADT is still not an enumeration because there is no enumerating \see{\VRef{s:AlgebraicDataType}}.
\begin{rust}
enum Week { Mon, Tues, Wed, Thu, Fri, Sat, Sun@,@ } // terminating comma
let mut week : Week = Week::Mon;
match week {
	Week::Mon $=>$ println!( "Mon" ),
	...
	Week::Sun $=>$ println!( "Sun" ),
}
\end{rust}

However, Rust allows direct setting of the ADT constructor, which means it is actually a tag.
\begin{cquote}
\setlength{\tabcolsep}{15pt}
\begin{tabular}{@{}ll@{}}
\begin{rust}
enum Week {
	Mon, Tues, Wed, // start 0
	Thu @= 10@, Fri,
	Sat, Sun,
}

\end{rust}
&
\begin{rust}
#[repr(u8)]
enum ADT {
	I(isize) @= 5@,
	F(f64) @= 10@,
	S(S) @= 0@,
}
\end{rust}
\end{tabular}
\end{cquote}
Through this integral tag, it is possible to enumerate, and when all tags represent the unit type, it behaves like \CC \lstinline[language=C++]{enum class}.
When tags represent non-unit types, Rust largely precludes accessing the tag because the semantics become meaningless.
Hence, the two mechanisms are largely disjoint, and only the enumeration component is discussed.

In detail, the @enum@ type has an implicit integer tag (discriminant) with a unique value for each variant type.
Direct initialization is achieved by a compile-time expression that generates a constant value.
Indirect initialization (without initialization, @Fri@/@Sun@) is auto-initialized: from left to right, starting at zero or the next explicitly initialized constant, incrementing by @1@.
There is an explicit cast from the tag to integer.
\begin{rust}
let mut mon : isize = Week::Mon as isize;
\end{rust}
An enumeration can be used in the @if@ and \lstinline[language=rust]{match} (@switch@) statements.
\begin{cquote}
\setlength{\tabcolsep}{8pt}
\begin{tabular}{@{}ll@{}}
\begin{c++}
if @week as isize@ == Week::Mon as isize {
	println!( "{:?}", week );
}


\end{c++}
&
\begin{c++}
match @week@ {
	Week::Mon | Week:: Tue | Week::Wed | Week::Thu
		| Week::Fri => println!( "weekday" ),
	Week::Sat | Week:: Sun $=>$ println!( "weekend" ),
}
\end{c++}
\end{tabular}
\end{cquote}
% However, there is no mechanism to iterate through an enumeration without casting to integral and positions versus values is not handled.
Like C/\CC, there is no mechanism to iterate through an enumeration.
It can only be approximated by a loop over a range of enumerators and only works if the enumerator values are a sequence of natural numbers.
\begin{c++}
for d in Week::Mon as isize ..= Week::Sun as isize {
	print!( "{:?} ", d );
}
0 1 2 @3 4 5 6 7 8 9@ 10 11 12 13
\end{c++}
% An enumeration type cannot declare an array dimension nor as a subscript.
There is no direct way to harmonize an enumeration and another data structure.
For example, there is no mapping from an enumerated type to an array type.
In terms of extensibility, there is no mechanism to subset or inherit from an enumeration.


\section{Swift}
\label{s:Swift}
% https://www.programiz.com/swift/online-compiler
Despite being named as enumeration, a Swift @enum@ is in fact a ADT: cases (enumerators) of an @enum@ can have heterogeneous types and be recursive.
% Like Rust, Swift @enum@ provides two largely independent mechanisms from a single language feature: an ADT and an enumeration.
When @enum@ is an ADT, pattern matching is used to discriminate among the variant types.
\begin{cquote}
\setlength{\tabcolsep}{20pt}
\begin{tabular}{@{}l@{\hspace{55pt}}ll@{}}
\begin{swift}
struct S {
	var i : Int,  j : Int
}
var s = S( i : 3, j : 5 )
@enum@ ADT {
	case I(Int)   $\C[1.125in]{// int}$
	case F(Float) $\C{// float}$
	case S(S)     $\C{// struct}\CRT$
}
\end{swift}
&
\begin{swift}
var adt : ADT
adt = .I( 3 );  print( adt )
adt = .F( 3.5 );  print( adt )
adt = .S( s );  print( adt )
@switch@ adt {  // pattern matching
	case .I(let i):  print( i )
	case .F(let f):  print( f )
	case .S(let s):  print( s.i, s.j )
}
\end{swift}
&
\begin{swift}
I(3)
F(3.5)
S(S(i: 3, j: 5))
3 5





\end{swift}
\end{tabular}
\end{cquote}
Note, after an @adt@'s type is known, the enumerator is inferred without qualification, \eg @.I(3)@.
% Normally an enumeration case needs a type qualification.
%However, when pattern matching @adt@ of type @ADT@, the @case@ context provides the type @ADT@ so no explicit type qualification is required. 

% An enumeration is created when \emph{all} the enumerators are unit-type, which is like a scoped, opaque enumeration.
Without type declaration for enumeration cases, the enumerators have unit-type, which is like a scoped, opaque enumeration.
\begin{swift}
enum Week { case Mon, Tue, Wed, Thu, Fri, Sat, Sun }; // unit-type
var week : Week = @Week.Mon@;
\end{swift}
% As well, it is possible to type \emph{all} the enumerators with a common type, and set different values for each enumerator;
% for integral types, there is auto-incrementing.
As well, it is possible to type associated values of enumeration cases with a common type. 
When enumeration cases are typed with a common integral type, Swift auto-initializes enumeration cases following the same initialization scheme as C language.
If an enumeration is typed with @string@, its cases are auto-initialized to case names (labels).
\begin{cquote}
\setlength{\tabcolsep}{15pt}
\begin{tabular}{@{}lll@{}}
\begin{swift}
enum WeekInt: @Int@ {
	case Mon, Tue, Wed, Thu = 10, Fri,
			Sat = 4, Sun // auto-incrementing
};
\end{swift}
&
\begin{swift}
enum WeekStr: @String@ {
	case Mon = "MON", Tue, Wed, Thu, Fri,
			Sat = "SAT", Sun
};
\end{swift}
\end{tabular}
\end{cquote}
An enumeration only supports equality comparison between enumerator values, unless it inherits from @Comparable@, adding relational operators @<@, @<=@, @>@, and @>=@.

An enumeration can have methods.
\begin{swift}
enum Week: @Comparable@ {
	case Mon, Tue, Wed, Thu, Fri, Sat, Sun // unit-type
	func @isWeekday() -> Bool@ { return self <= .Fri }  // methods
	func @isWeekend() -> Bool@ { return .Sat <= self }
};
\end{swift}
An enumeration can be used in the @if@ and @switch@ statements, where @switch@ must be exhaustive or have a @default@.
\begin{cquote}
\setlength{\tabcolsep}{15pt}
\begin{tabular}{@{}ll@{}}
\begin{swift}
if @week <= .Fri@ {
	print( "weekday" );
}


\end{swift}
&
\begin{swift}
switch @week@ {
	case .Mon: print( "Mon" )
	...
	case .Sun: print( "Sun" )
}
\end{swift}
\end{tabular}
\end{cquote}
Enumerating is accomplished by inheriting from @CaseIterable@ protocol, which has a static @enum.@ @allCases@ property that returns a collection of all the cases for looping over an enumeration type or variable.
Like \CFA, Swift's default enumerator output is the case name (label). An enumerator of a typed enumeration has an attribute 
@rawValue@ that return its case value.
\begin{swift}
enum Week: Comparable, @CaseIterable@ {
	case Mon, Tue, Wed, Thu, Fri, Sat, Sun // unit-type
};
for day in Week@.allCases@ { 
	print( day, terminator:" " ) 
}
Mon Tue Wed Thu Fri Sat Sun 
\end{swift}


\begin{cquote}
\setlength{\tabcolsep}{15pt}
\begin{tabular}{@{}lll@{}}
\begin{swift}
enum WeekInt: @Int@, CaseIterable {
	case Mon, Tue, Wed, Thu = 10, Fri,
			Sat = 4, Sun // auto-incrementing
};
for day in WeekInt.allCases {
	print( day@.rawValue@, terminator:" " ) 
}
0 1 2 10 11 4 5 
\end{swift}
&
\begin{swift}
enum WeekStr: @String@, CaseIterable {
	case Mon = "MON", Tue, Wed, Thu, Fri,
			Sat = "SAT", Sun
};
for day in WeekStr.allCases { 
	print( day@.rawValue@, terminator:" " ) 
}
MON Tue Wed Thu Fri SAT Sun 
\end{swift}
\end{tabular}
\end{cquote}

There is a safe bidirectional conversion from typed enumerator to @rawValue@ and vice versa.
\begin{swift}
if let opt = WeekInt( rawValue: 0 ) {  // test optional return value
	print( opt.rawValue, opt )  // 0 Mon
} else {
	print( "invalid weekday lookup" )
}
\end{swift}
% Conversion from @rawValue@ to enumerator may fail (bad lookup), so the result is an optional value.
In the previous example, the initialization of @opt@ fails if there is no enumeration value equal to 0, resulting in a @nil@ value.
Initialization from a raw value is considered an expensive operation because it requires a value lookup.


\section{Python 3.13}
% https://docs.python.org/3/howto/enum.html

Python is a dynamically-typed reflexive programming language with multiple incompatible versions.
The generality of the language makes it possible to extend existing or build new language features.
As a result, discussing Python enumerations is a moving target, because if a feature does not exist, it can often be created with varying levels of complexity within the language.
Therefore, the following discussion is (mostly) restricted to the core enumeration features in Python 3.13.

A Python enumeration is not a basic type;
it is a @class@ inheriting from the @Enum@ class.
The @Enum@ class presents a set of scoped enumerators, where each enumerator is a pair object with a \emph{constant} string name and an arbitrary value.
Hence, an enumeration instance is a fixed type (enumeration pair), and its value is the type of one of the enumerator pairs.

The enumerator value fields must be explicitly initialized and be \emph{unique}.
\begin{python}
class Week(!Enum!): Mon = 1; Tue = 2; Wed = 3; Thu = 4; Fri = 5; Sat = 6; Sun = 7
\end{python}
and/or explicitly auto-initialized with @auto@ method, \eg:
\begin{python}
class Week(Enum): Mon = 1; Tue = 2; Wed = 3; Thu = 10; Fri = !auto()!; Sat = 4; Sun = !auto()!
Mon : 1 Tue : 2 Wed : 3 Thu : 10 Fri : !11! Sat : 4 Sun : !12!
\end{python}
@auto@ is controlled by member @_generate_next_value_()@, which by default returns one plus the highest value among enumerators, and can be overridden:
\begin{python}
@staticmethod
def _generate_next_value_( name, start, count, last_values ):
	return name
\end{python}

There is no direct concept of restricting the enumerators in an enumeration \emph{instance} because dynamic typing changes the type.
\begin{python}
class RGB(Enum): Red = 1; Green = 2; Blue = 3
day : Week = Week.Tue;		$\C{\# type is Week}$
!day = RGB.Red!				$\C{\# type is RGB}$
!day : Week = RGB.Red!		$\C{\# type is RGB}$
\end{python}
The enumerators are constants and cannot be reassigned.
Hence, while enumerators can be different types,
\begin{python}
class Diff(Enum): Int = 1; Float = 3.5; Str = "ABC"
\end{python}
it is not an ADT because the enumerator names are not constructors.

An enumerator initialized with the same value is an alias and invisible at the enumeration level, \ie the alias is substituted for its aliases.
\begin{python}
class WeekD(Enum): Mon = 1; Tue = 2; Wed = 3; Thu = !10!; Fri = !10!; Sat = !10!; Sun = !10!
\end{python}
Here, the enumeration has only 4 enumerators and 3 aliases.
An alias is only visible by dropping down to the @class@ level and asking for class members.
Aliasing is prevented using the @unique@ decorator.
\begin{python}
!@unique!
class DupVal(Enum): One = 1; Two = 2; Three = !3!; Four = !3!
ValueError: duplicate values found in <enum 'DupVal'>: Four -> Three
\end{python}

\begin{lrbox}{\myboxA}
\begin{python}
def by_position(enum_type, position):
	for index, value in enumerate(enum_type):
		if position == index: return value
	raise Exception("by_position out of range")
\end{python}
\end{lrbox}
There are bidirectional enumeration pseudo-functions for label and value, but there is no concept of access using ordering (position).\footnote{
There is an $O(N)$ mechanism to access an enumerator's value by position. \newline \usebox\myboxA}
\begin{cquote}
\setlength{\tabcolsep}{15pt}
\begin{tabular}{@{}ll@{}}
\begin{python}
Week.Thu.value == 4;
Week.Thu.name == "Thu";
\end{python}
&
\begin{python}
Week( 4 ) == Week.Thu
Week["Thu"].value == 4
\end{python}
\end{tabular}
\end{cquote}
@Enum@ only supports equality comparison between enumerator values.
There are multiple library extensions to @Enum@, \eg @OrderedEnum@ recipe class, adding relational operators @<@, @<=@, @>@, and @>=@.

An enumeration \lstinline[language=python]{class} can have methods.
\begin{python}
class Week(!OrderedEnum!):
	Mon = 1; Tue = 2; Wed = 3; Thu = 4; Fri = 5; Sat = 6; Sun = 7
	def !isWeekday(self)!:		# methods
		return Week(self.value) !<=! Week.Fri
	def !isWeekend(self)!:
		return Week.Sat !<=! Week(self.value) 
\end{python}

An enumeration can be used in the @if@ and @switch@ statements but only for equality tests, unless extended to @OrderedEnum@.
\begin{cquote}
\setlength{\tabcolsep}{12pt}
\begin{tabular}{@{}ll@{}}
\begin{python}
if day <= Week.Fri :
	print( "weekday" );



\end{python}
&
\begin{python}
match day:
	case Week.Mon | Week.Tue | Week.Wed | Week.Thu | Week.Fri:
		print( "weekday" );
	case Week.Sat | Week.Sun:
		print( "weekend" );
\end{python}
\end{tabular}
\end{cquote}
Looping is performed using the enumeration type or @islice@ from @itertools@ based on position.
\begin{python}
for day in !Week!:					$\C[2.25in]{\# Mon : 1 Tue : 2 Wed : 3 Thu : 4 Fri : 5 Sat : 6 Sun : 7}$
	print( day.name, ":", day.value, end=" " )
for day in !islice(Week, 0, 5)!:	$\C{\# Mon : 1 Tue : 2 Wed : 3 Thu : 4 Fri : 5}$
	print( day.name, ":", day.value, end=" " )
for day in !islice(Week, 5, 7)!:	$\C{\# Sat : 6 Sun : 7}$
	print( day.name, ":", day.value, end=" " )
for day in !islice(Week,0, 7, 2)!:	$\C{\# Mon : 1 Wed : 3 Fri : 5 Sun : 7}\CRT$
	print( day.name, ":", day.value, end=" " )
\end{python}
Iterating that includes alias names only (strings) is done using attribute @__members__@.
\begin{python}
for day in WeekD.__members__:
	print( day, ":", end=" " )
Mon : Tue : Wed : Thu : Fri : Sat : Sun 
\end{python}

Enumeration subclassing is allowed only if the enumeration base-class does not define any members.
\begin{python}
class WeekE(OrderedEnum): !pass!;  # no members
class WeekDay(WeekE): Mon = 1; Tue = 2; Wed = 3; Thu = 4; Fri = 5;
class WeekEnd(WeekE): Sat = 6; Sun = 7
\end{python}
Here, type @WeekE@ is an abstract type because dynamic typing never uses it.
\begin{cquote}
\setlength{\tabcolsep}{25pt}
\begin{tabular}{@{}ll@{}}
\begin{python}
print( type(WeekE) )
day : WeekE = WeekDay.Fri	# set type
print( type(day), day )
day = WeekEnd.Sat			    # set type
print( type(day), day )
\end{python}
&
\begin{python}
<$class$ 'enum.EnumType'>

<enum 'WeekDay'> WeekDay.Fri

<enum 'WeekEnd'> WeekEnd.Sat
\end{python}
\end{tabular}
\end{cquote}

There are a number of supplied enumeration base-types: @IntEnum@, @StrEnum@, @IntFalg@, @Flag@, which restrict the values in an enum using multi-inheritance.
@IntEnum@ is a subclass of @int@ and @Enum@, allowing enumerator comparison to @int@ and other enumerators of this type (like C enumerators).
@StrEnum@ is the same as @IntEnum@ but a subclass of the string type \lstinline[language=python]{str}.
@IntFlag@, is a restricted subclass of @int@ where the enumerators can be combined using the bitwise operators (@&@, @|@, @^@, @~@) and the result is an @IntFlag@ member.
@Flag@ is the same as @IntFlag@ but cannot be combined with, nor compared against, any other @Flag@ enumeration, nor @int@.
Auto increment for @IntFlag@ and @Flag@ is by powers of 2.
Enumerators that are combinations of single-bit enumerators are aliases and, hence, invisible.
The following is an example for @Flag@.
\begin{python}
class WeekF(Flag): Mon = 1; Tue = 2; Wed = 4; Thu = !auto()!; Fri = 16; Sat = 32; Sun = 64; \
	  Weekday = Mon | Tue | Wed | Thu | Fri; \
	  Weekend = Sat | Sun
print( f"0x{repr(WeekF.Weekday.value)} 0x{repr(WeekF.Weekend.value)}" )
0x31 0x96
\end{python}
It is possible to enumerate through a @Flag@ enumerator (no aliases):
\begin{python}
for day in WeekF:
	print( f"{day.name}: {day.value}", end=" ")
Mon: 1 Tue: 2 Wed: 4 Thu: 8 Fri: 16 Sat: 32 Sun: 64 
\end{python}
and a combined alias enumerator for @Flag@.
\begin{cquote}
\setlength{\tabcolsep}{15pt}
\begin{tabular}{@{}ll@{}}
\begin{python}
weekday = WeekF.Weekday
for day in weekday:
	print( f"{day.name}:"
		   f" {day.value}", end=" " )
Mon: 1 Tue: 2 Wed: 4 Thu: 8 Fri: 16 
\end{python}
&
\begin{python}
weekend = WeekF.Weekend
for day in weekend:
	print( f"{day.name}:"
		   f" {day.value}", end=" " )
Sat: 32 Sun: 64 
\end{python}
\end{tabular}
\end{cquote}


\section{OCaml}

% https://ocaml.org/docs/basic-data-types#enumerated-data-types
% https://dev.realworldocaml.org/runtime-memory-layout.html

Like Swift (\VRef{s:Swift}) and Haskell (\VRef{s:AlgebraicDataType}), OCaml @enum@ provides two largely independent mechanisms from a single language feature: an ADT and an enumeration.
When @enum@ is an ADT, pattern matching is used to discriminate among the variant types.
\begin{cquote}
\setlength{\tabcolsep}{20pt}
\begin{tabular}{@{}l@{\hspace{35pt}}ll@{}}
\begin{ocaml}
type s = { i : int; j : int }
let sv : s = { i = 3; j = 5 }
@type@ adt =
	I of int |    $\C[1in]{// int}$
	F of float |  $\C{// float}$
	S of s        $\C{// struct}\CRT$


\end{ocaml}
&
\begin{ocaml}
let adtprt( adtv : adt ) =
	@match@ adtv with (* pattern matching *)
		I i -> printf "%d\n" i |
		F f -> printf "%g\n" f |
		S sv -> printf "%d %d\n" sv.i sv.j
let adtv : adt = I(3)       let _ = adtprt( adtv )
let adtv : adt = F(3.5)   let _ = adtprt( adtv )
let adtv : adt = S(sv)    let _ = adtprt( adtv )
\end{ocaml}
&
\begin{ocaml}
3
3.5
3 5





\end{ocaml}
\end{tabular}
\end{cquote}
% (Note, after an @adtv@'s type is know, the enumerator is inferred without qualification, \eg @I(3)@.)

The type names are independent of the type value and mapped to an opaque, ascending, integral tag, starting from 0, supporting relational operators @<@, @<=@, @>@, and @>=@.
\begin{cquote}
\setlength{\tabcolsep}{10pt}
\begin{tabular}{@{}l@{\hspace{25pt}}ll@{}}
\begin{ocaml}
let silly( adtv : adt ) =
	if adtv <= F(3.5) then
		printf "<= F\n"
	else if adtv >= S(sv) then
		printf ">= S\n"
\end{ocaml}
&
\begin{ocaml}
let adtv : adt = I(3)       let _ = silly( adtv )
let adtv : adt = F(3.5)   let _ = silly( adtv )
let adtv : adt = S(sv)    let _ = silly( adtv )


\end{ocaml}
&
\begin{ocaml}
<= F
<= F
>= S


\end{ocaml}
\end{tabular}
\end{cquote}
In the example, type values must be specified (any appropriate values work) but ignored in the relational comparison of the type tag.

An enumeration is created when \emph{all} the enumerators are unit-type, which is like a scoped, opaque enumeration, where only the type tag is used.
\begin{ocaml}
type week = Mon | Tue | Wed | Thu | Fri | Sat | Sun
let day : week = Mon
\end{ocaml}
Since the type names are opaque, a type-tag value cannot be explicitly set nor can it have a type other than integral.

As seen, a type tag can be used in the @if@ and \lstinline[language=ocaml]{match} statements, where \lstinline[language=ocaml]{match} must be exhaustive or have a default case.

While OCaml enumerators have an ordering following the definition order, they are not enumerable.
To iterate over all enumerators, an OCaml type needs to derive from the @enumerate@ PPX (Pre-Preocessor eXtension), which appends a list of all enumerators to the program abstract syntax tree (AST).
However, as stated in the documentation, @enumerate@ PPX does not guarantee the order of the list.
PPX is beyond the scope of OCaml native language and it is a preprocessor directly modifying a parsed AST. In conclusion, there is no enumerating mechanism within the scope of OCaml language.

New types can be formed as a composition of existing types.
\begin{ocaml}
type weekday = Mon | Tue | Wed | Thu | Fri
type weekend = Sat | Sun
type week = Weekday of weekday | Weekend of weekend
let day : week = Weekend Sun
\end{ocaml}
The type @week@ is the sum of @weekday@ and @weekend@, \ie @week@ has all the enumerators from the set @weekday@ and @weekend@.
The sum type construction resembles containment inheritance from non-functional programming discipline, with the sum type being a wrapper class that contains one of its parent types.
The wrapper is unwrapped with pattern matching.
\begin{cquote}
\begin{tabular}{@{}ll@{}}
\begin{ocaml}
type weekday = Mon | Tue | Wed | Thu | Fri
type weekend = Sat | Sun
type week = Weekday of weekday |
				 Weekend of weekend
let wd : weekday = Mon
let _ = match wd with
	Mon -> printf "Mon " | _ -> ()
let we : weekend = Sun
let _ = match we with
	Sun -> printf "Sun " | _ -> ()
let day : week = Weekend Sun
let _ = match day with
	Weekend Sun -> printf "Sun\n" | _ -> ()

\end{ocaml}
&
\begin{cfa}
enum() weekday { Mon, Tue, Wed, Thu, Fri };
enum() weekend { Sat, Sun };
enum() week { inline weekday, inline weekend };
int main() {
	weekday wd = Mon;

	printf( "%s ", label( wd ) );
	weekend we = Sun;

	printf( "%s ", label( we ) );
	week day = Sun;

	printf( "%s\n", label( day ) );
}
\end{cfa}
\\
\begin{cfa}
Mon Sun Sun
\end{cfa}
\end{tabular}
\end{cquote}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{comment}
Date: Wed, 13 Mar 2024 10:52:34 -0400
Subject: Re: OCaml
To: "Peter A. Buhr" <pabuhr@uwaterloo.ca>
From: Gregor Richards <gregor.richards@uwaterloo.ca>

On 3/12/24 18:34, Peter A. Buhr wrote:
> Gregor, attached is a section Jiada wrote on OCaml (1-page).
> Does it reflect our discussion about functional languages and enumerations?

Yeah, I think so. The most important part, i.e., that once they're
parameterized they're not really enumerations at all, is covered clearly
enough.

A couple quibbles:

<<a list of untyped tags>>

This is true, but leaking implementation details. These are nullary datatype
constructors. Indeed, you later talk about "tagged variants", which are really
just parameterized variants, using the term "tag" differently, confusing the
term "tag" further.

<<Because week is a summation of values Mon to Sun, it is a sum type in
turns of the functional-programming paradigm>>

It is a *union* of values and is a *union* type.

With valediction,
  - Gregor Richards


Date: Thu, 14 Mar 2024 21:45:52 -0400
Subject: Re: OCaml "enums" do come with ordering
To: "Peter A. Buhr" <pabuhr@uwaterloo.ca>
From: Gregor Richards <gregor.richards@uwaterloo.ca>

On 3/14/24 21:30, Peter A. Buhr wrote:
> I've marked 3 places with your name to shows places with enum ordering.
>
> open Printf
> type week = Mon | Tue | Wed | Thu | Fri | Sat | Sun
> let day : week = Mon
> let take_class( d : week ) =
> 	if d <= Fri then				(* Gregor *)
> 		printf "week\n"
> 	else if d >= Sat then			(* Gregor *)
> 		printf "weekend\n";
> 	match d with
> 		Mon | Wed -> printf "CS442\n" |
> 		Tue | Thu -> printf "CS343\n" |
> 		Fri -> printf "Tutorial\n" |
> 		_ -> printf "Take a break\n"
>
> let _ = take_class( Mon ); take_class( Sat );
>
> type colour = Red | Green of string | Blue of int * float
> let c = Red
> let _ = match c with Red -> printf "Red, "
> let c = Green( "abc" )
> let _ = match c with Green g -> printf "%s, " g
> let c = Blue( 1, 1.5 )
> let _ = match c with Blue( i, f ) -> printf "%d %g\n" i f
>
> let check_colour(c: colour): string =
> 	if c < Green( "xyz" ) then		(* Gregor *)
> 		printf "green\n";
> 	match c with
> 		Red -> "Red" |
> 		Green g -> g |
> 		Blue(i, f) -> string_of_int i ^ string_of_float f
> let _ = check_colour( Red ); check_colour( Green( "xyz" ) );
>
> type stringList = Empty | Pair of string * stringList
> let rec len_of_string_list(l: stringList): int =
> 	match l with
> 		Empty -> 0 |
> 		Pair(_ , r) -> 1 + len_of_string_list r
>
> let _ = for i = 1 to 10 do
> 	printf "%d, " i
> done
>
> (* Local Variables: *)
> (* tab-width: 4 *)
> (* compile-command: "ocaml test.ml" *)
> (* End: *)

My functional-language familiarity is far more with Haskell than OCaml.  I
mostly view OCaml through a lens of "it's Haskell but with cheating".  Haskell
"enums" (ADTs) aren't ordered unless you specifically and manually put them in
the Ord typeclass by defining the comparators.  Apparently, OCaml has some
other rule, which I would guess is something like "sort by tag then by order of
parameter". Having a default behavior for comparators is *bizarre*; my guess
would be that it gained this behavior in its flirtation with object
orientation, but that's just a guess (and irrelevant).

This gives a total order, but not enumerability (which would still be
effectively impossible or even meaningless since enums are just a special case
of ADTs).

With valediction,
  - Gregor Richards

Date: Wed, 20 Mar 2024 18:16:44 -0400
Subject: Re:
To: "Peter A. Buhr" <pabuhr@uwaterloo.ca>
From: Gregor Richards <gregor.richards@uwaterloo.ca>


On 3/20/24 17:26, Peter A. Buhr wrote:
> Gregor, everyone at this end would like a definition of "enumerability". Can
> you formulate one?

According to the OED (emphasis added to the meaning I'm after):

enumerate (verb, transitive). To count, ascertain the number of; **more
usually, to mention (a number of things or persons) separately, as if for the
purpose of counting**; to specify as in a list or catalogue.

With C enums, if you know the lowest and highest value, you can simply loop
over them in a for loop (this is, of course, why so many enums come with an
ENUM_WHATEVER_LAST value). But, I would be hesitant to use the word "loop" to
describe enumerability, since in functional languages, you would recurse for
such a purpose.

In Haskell, in order to do something with every member of an "enumeration", you
would have to explicitly list them all. The type system will help a bit since
it knows if you haven't listed them all, but you would have to statically have
every element in the enumeration.  If somebody added new elements to the
enumeration later, your code to enumerate over them would no longer work
correctly, because you can't simply say "for each member of this enumeration do
X". In Haskell that's because there aren't actually enumerations; what they use
as enumerations are a degenerate form of algebraic datatypes, and ADTs are
certainly not enumerable. In OCaml, you've demonstrated that they impose
comparability, but I would still assume that you can't make a loop over every
member of an enumeration. (But, who knows!)

Since that's literally what "enumerate" means, it seems like a rather important
property for enumerations to have ;)

With valediction,
  - Gregor Richards


From: Andrew James Beach <ajbeach@uwaterloo.ca>
To: Gregor Richards <gregor.richards@uwaterloo.ca>, Peter Buhr <pabuhr@uwaterloo.ca>
CC: Michael Leslie Brooks <mlbrooks@uwaterloo.ca>, Fangren Yu <f37yu@uwaterloo.ca>,
	Jiada Liang <j82liang@uwaterloo.ca>
Subject: Re: Re:
Date: Thu, 21 Mar 2024 14:26:36 +0000

Does this mean that not all enum declarations in C create enumerations? If you
declare an enumeration like:

enum Example {
	Label,
	Name = 10,
	Tag = 3,
};

I don't think there is any way to enumerate (iterate, loop, recurse) over these
values without listing all of them.


Date: Thu, 21 Mar 2024 10:31:49 -0400
Subject: Re:
To: Andrew James Beach <ajbeach@uwaterloo.ca>, Peter Buhr <pabuhr@uwaterloo.ca>
CC: Michael Leslie Brooks <mlbrooks@uwaterloo.ca>, Fangren Yu <f37yu@uwaterloo.ca>,
    Jiada Liang <j82liang@uwaterloo.ca>
From: Gregor Richards <gregor.richards@uwaterloo.ca>

I consider this conclusion reasonable. C enums can be nothing more than const
ints, and if used in that way, I personally wouldn't consider them as
enumerations in any meaningful sense, particularly since the type checker
essentially does nothing for you there. Then they're a way of writing consts
repeatedly with some textual indicator that these definitions are related; more
namespace, less enum.

When somebody writes bitfield members as an enum, is that *really* an
enumeration, or just a use of the syntax for enums to keep related definitions
together?

With valediction,
  - Gregor Richards


Date: Tue, 16 Apr 2024 11:04:51 -0400
Subject: Re: C unnamed enumeration
To: "Peter A. Buhr" <pabuhr@uwaterloo.ca>
CC: <ajbeach@uwaterloo.ca>, <j82liang@uwaterloo.ca>, <mlbrooks@uwaterloo.ca>,
        <f37yu@uwaterloo.ca>
From: Gregor Richards <gregor.richards@uwaterloo.ca>

On 4/16/24 09:55, Peter A. Buhr wrote:
> So what is a variant? Is it a set of tag names, which might be a union or is it
> a union, which might have tag names?

Your tagless variant bears no resemblance to variants in any functional
programming language. A variant is a tag AND a union. You might not need to put
anything in the union, in which case it's a pointless union, but the named tag
is absolutely mandatory. That's the thing that varies.

I was unaware of std::variant. As far as functional languages are concerned,
std::variant IS NOT A VARIANT. Perhaps it would be best to use the term ADT for
the functional language concept, because that term has no other meanings.

An ADT cannot not have a named tag. That's meaningless. The tag is the data
constructor, which is the thing you actually define when you define an ADT. It
is strictly the union that's optional.

With valediction,
  - Gregor Richards
\end{comment}


\section{Comparison}

\VRef[Table]{t:FeatureLanguageComparison} shows a comparison of enumeration features and programming languages with the explaination of categories below.
The features are high-level and may not capture nuances within a particular language. 

\begin{table}
\caption{Enumeration Feature / Language Comparison}
\label{t:FeatureLanguageComparison}
\small
\setlength{\tabcolsep}{3pt}
\newcommand{\CM}{\checkmark}
\begin{tabular}{r|c|c|c|c|c|c|c|c|c|c|c|c|c}
				&Pascal	& Ada			&\Csharp   & OCaml  & Java	&Golang   & Rust		& Swift			& Python& C		& \CC	& \CFA	\\
\hline
enum			&Dialect& \CM    		& \CM      & ADT    & \CM   & @const@ &ADT/\CM	    &ADT/\CM		& \CM   &\CM    &\CM   &\CM\\
\hline
\hline
opaque			& \CM    &				&		   & \CM    & \CM   &		  & \CM         & \CM   		&		&		&		& \CM	\\
\hline
typed			& Int    & Int   		& Int	  & H     & U     & H       & U/H         & U/H           & H	    & Int	& Int	& U	\\
\hline
safety          & \CM   & \CM   		&          & \CM 	& \CM   &		  & \CM  		& \CM    		&		&		& \CM	& \CM	\\
\hline
posn ordered	& Implied & Implied     &          & \CM    &       &		  &	  		    &        		&       & 	    &       & \CM	\\
\hline
unique values	& \CM   & \CM           &           &\CM	&       &      &	  		    & \CM   		&    	& 	    & 	    & 	  \\
\hline
auto-init		& \CM   & all or none   & \CM      & N/A &       & \CM     & \CM   	    & \CM   		& \CM   & \CM	& \CM	& \CM	\\
\hline
(Un)Scoped		& U 	& U     		& S        & S      & S 	& U 	  & S 		    & S 			& S 	& U		& U/S	& U/S	\\
\hline
overload 		&		& \CM			& 	       &   	    &      &		  &  		    & 			    & 	   &		&   	& \CM	\\
\hline
loop			& \CM 	& \CM 			&		   &		&		&		  &	  		    &		        & \CM	&		&		& \CM	\\
\hline
arr. dim.		& \CM   & \CM           &		   &		  &		    &		&	  	  &		            &		 &    	&		& \CM \\
\hline
subset			& \CM   & \CM    		&         &      &		&		  &	  		    &		        &		&		&		& \CM	\\
\hline
superset		&		&				&		  & \CM   &		    &		  &\CM        &\CM            &		&		&		& \CM	\\
\end{tabular}
\end{table}

\begin{enumerate}
\item opaque: an enumerator cannot be used as its underlying representation or implemented in terms of an ADT.
\item typed: H $\Rightarrow$ heterogeneous, \ie enumerator values may be different types. \\
U $\Rightarrow$ homogenous, \ie enumerator values have the same type.
\item safety: An enumeration variable can only hold a value from its defined enumerators.
\item posn ordered: enumerators have defined ordering based on enumerator declaration order.
Position ordered is implied if the enumerator values must be strictly increasingly.
\item unique value: enumerators must have a unique value.
\item auto-init: Values are auto-initializable by language specification. \\
It is not appliable to OCaml because OCaml enumeration has unit type.
\item (Un)Scoped: U $\Rightarrow$ enumerators are projected into the containing scope.
S $\Rightarrow$ enumerators are contained in the enumeration scope and require qualification.
\item overload: An enumerator label can be used without type qualification in a context where multiple enumerations have defined the label.
\item loop: Enumerate without the need to convert an enumeration to another data structure.
\item arr. dim: An enumeration can be used directly as an array dimension, and enumerators can be mapped to an array element (not a conversion to integer type).
\item subset: Name a subset of enumerators as a new type.
\item superset: Create a new enumeration that contains all enumerators from pre-defined enumerations.
\end{enumerate}
