source: doc/theses/jiada_liang_MMath/relatedwork.tex @ acab1bd

Last change on this file since acab1bd was c1c0efdb, checked in by Peter A. Buhr <pabuhr@…>, 13 hours ago

last proofread of thesis

  • Property mode set to 100644
File size: 57.6 KB
Line 
1\chapter{Related Work}
2\label{s:RelatedWork}
3
4\begin{comment}
5An algebraic data type (ADT) can be viewed as a recursive sum of product types.
6A sum type lists values as members.
7A member in a sum type definition is known as a data constructor.
8For example, C supports sum types union and enumeration (enum).
9An enumeration in C can be viewed as the creation of a list of zero-arity data constructors.
10A union instance holds a value of one of its member types.
11Defining a union does not generate new constructors.
12The definition of member types and their constructors are from the outer lexical scope.
13
14In general, an \newterm{algebraic data type} (ADT) is a composite type, \ie, a type formed by combining other types.
15Three common classes of algebraic types are \newterm{array type}, \ie homogeneous types, \newterm{product type}, \ie heterogeneous tuples and records (structures), and \newterm{sum type}, \ie tagged product-types (unions).
16Enumerated types are a special case of product/sum types with non-mutable fields, \ie initialized (constructed) once at the type's declaration, possible restricted to compile-time initialization.
17Values of algebraic types are access by subscripting, field qualification, or type (pattern) matching.
18\end{comment}
19
20Enumeration-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}.
21Among these languages, there is a large set of overlapping features, but each language has its own unique extensions and restrictions.
22
23
24\section{Pascal}
25\label{s:Pascal}
26
27Pascal introduced the \lstinline[language=Pascal]{const} aliasing declaration binding a name to a constant literal/expression.
28\begin{pascal}
29const Three = 2 + 1;   NULL = NIL;   PI = 3.14159;   Plus = '+';   Fred = 'Fred';
30\end{pascal}
31As stated, this mechanism is not an enumeration because there is no specific type (pseudo enumeration).
32Hence, there is no notion of a (possibly ordered) set.
33The type of each constant name (enumerator) is inferred from the constant-expression type.
34
35Pascal introduced the enumeration type characterized by a set of ordered, unscoped identifiers (enumerators), which are not overloadable.\footnote{%
36Pascal 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).}
37\begin{pascal}
38type Week = ( Mon, Tue, Wed, Thu, Fri, Sat, Sun );
39\end{pascal}
40Object initialization and assignment are restricted to the enumerators of this type.
41Enumerators are auto-initialized from left to right, starting at zero and incrementing by 1.
42Enumerators \emph{cannot} be explicitly initialized.
43Pascal provides a predefined type \lstinline[language=Pascal]{Boolean} defined as:
44\begin{pascal}
45type Boolean = ( false, true );
46\end{pascal}
47The enumeration ordering supports the relational operators @=@, @<>@, @<@, @<=@, @>=@, and @>@, provided both operands are the same (sub)type.
48
49The following auto-generated pseudo-functions exist for all enumeration types:
50\begin{cquote}
51\begin{tabular}{@{}ll@{}}
52@succ( T )@     & @succ( Tue ) = Wed@ \\
53@pred( T )@     & @pred( Tue ) =  Mon@ \\
54@ord( T )@      & @ord( Tue ) = 1@
55\end{tabular}
56\end{cquote}
57
58Pascal provides \emph{consecutive} subsetting of an enumeration using a subrange type.
59\begin{pascal}
60type Week = ( Mon, Tue, Wed, Thu, Fri, Sat, Sun );
61           Weekday = @Mon..Fri@;   { subtype }
62           Weekend = @Sat..Sun@;
63var day : Week;
64         wday : Weekday;
65         wend : Weekend;
66\end{pascal}
67Hence, the ordering of the enumerators is crucial to provide the necessary ranges.
68There is a bidirectional assignment between the enumeration and its subranges.
69\begin{pascal}
70day := Sat;
71@wday := day;@                  $\C[1.5in]{\{ check \}}$
72wend := day;                    $\C{\{ maybe check \}}$
73day := Mon;
74wday := day;                    $\C{\{ maybe check \}}$
75@wend := day;@                  $\C{\{ check \}}$
76day := wday;                    $\C{\{ no check \}}$
77day := wend;                    $\C{\{ no check \}}\CRT$
78\end{pascal}
79A static/dynamic range check should be performed to verify the values assigned to subtypes.
80(Free Pascal does not check and aborts in certain situations, like writing an invalid enumerator.)
81
82An enumeration can be used in the @if@ and @case@ statements or iterating constructs.
83\begin{cquote}
84\setlength{\tabcolsep}{15pt}
85\begin{tabular}{@{}ll@{}}
86\begin{pascal}
87day := Mon;
88if @day@ = wday then
89        Writeln( day );
90if @day@ <= Fri then
91        Writeln( 'weekday');
92Mon
93weekday
94\end{pascal}
95&
96\begin{pascal}
97
98case @day@ of
99  Mon..Fri :
100        Writeln( 'weekday');
101  Sat..Sun :
102        Writeln( 'weekend')
103end;
104weekday
105\end{pascal}
106\end{tabular}
107\end{cquote}
108\begin{cquote}
109\setlength{\tabcolsep}{15pt}
110\begin{tabular}{@{}ll@{}}
111\begin{pascal}
112while day <= Sun do begin
113        Write( day, ' ' );
114        day := succ( day );
115end;
116Mon Tue Wed Thu Fri Sat Sun
117\end{pascal}
118&
119\begin{pascal}
120for day := Mon to Sun do begin
121        Write( day, ' ' );
122
123end;
124Mon Tue Wed Thu Fri Sat Sun
125\end{pascal}
126\end{tabular}
127\end{cquote}
128Note that subtypes @Weekday@ and @Weekend@ cannot be used to define a case or loop range.
129
130An enumeration type can be used as an array dimension and subscript.
131\begin{pascal}
132Lunch : array( @Week@ ) of Time;
133for day in Week loop
134        Lunch( @day@ ) := ... ;       { set lunch time }
135end loop;
136\end{pascal}
137
138Free Pascal~\cite[\S~3.1.1]{FreePascal} is a modern, object-oriented version of Pascal, with a C-style enumeration type.
139Enumerators can be assigned explicit values assigned in ascending numerical order using a constant expression, and the range can be non-consecutive.
140\begin{pascal}
141type Count = ( Zero, One, Two, Ten = 10, Eleven );
142\end{pascal}
143Pseudo-functions @pred@ and @succ@ can only be used if the range is consecutive.
144Enumerating gives extraneous values.
145\begin{pascal}
146for cnt := Zero to Eleven do begin
147        Write( ord( cnt ), ' ' );
148end;
1490 1 2 @3 4 5 6 7 8 9@ 10 11
150\end{pascal}
151
152The 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.
153The integral size can be explicitly specified using compiler directive @$PACKENUM@~$N$, where $N$ is the number of bytes, \eg:
154\begin{pascal}
155Type @{$\color{red}\$$PACKENUM 1}@ SmallEnum = ( one, two, three );
156                @{$\color{red}\$$PACKENUM 4}@ LargeEnum = ( BigOne, BigTwo, BigThree );
157Var S : SmallEnum; { 1 byte }
158          L : LargeEnum; { 4 bytes}
159\end{pascal}
160
161
162\section{Ada}
163\label{s:Ada}
164
165An Ada enumeration type is a set of ordered, unscoped identifiers (enumerators) bound to \emph{unique} \newterm{literals}.\footnote{%
166Ada 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).}
167\begin{ada}
168type Week is ( Mon, Tue, Wed, Thu, Fri, Sat, Sun ); -- literals (enumerators)
169\end{ada}
170Object initialization and assignment are restricted to the enumerators of this type.
171While Ada enumerators are unscoped, like C, Ada enumerators are overloadable.
172\begin{ada}
173type RGB is ( @Red@, @Green@, Blue );
174type Traffic_Light is ( @Red@, Yellow, @Green@ );
175\end{ada}
176Like \CFA, Ada uses a type-resolution algorithm, including the left-hand side of the assignment, to disambiguate among overloaded identifiers.
177\VRef[Figure]{f:AdaEnumeration} shows how ambiguity is handled using a cast, \eg \lstinline[language=ada]{RGB'(Red)}.
178
179\begin{figure}
180\begin{ada}
181with Ada.Text_IO; use Ada.Text_IO;
182procedure test is
183        type RGB is ( @Red@, Green, Blue );
184        type Traffic_Light is ( @Red@, Yellow, Green );         -- overload
185        procedure @Red@( Colour : RGB ) is begin            -- overload
186                Put_Line( "Colour is " & RGB'Image( Colour ) );
187        end Red;
188        procedure @Red@( TL : Traffic_Light ) is begin       -- overload
189                Put_Line( "Light is " & Traffic_Light'Image( TL ) );
190        end Red;
191begin
192        @Red@( Blue );                           -- RGB
193        @Red@( Yellow );                                -- Traffic_Light
194        @Red@( @RGB'(Red)@ );           -- ambiguous without cast
195end test;
196\end{ada}
197\caption{Ada Enumeration Overload Resolution}
198\label{f:AdaEnumeration}
199\end{figure}
200
201Enumerators without initialization are auto-initialized from left to right, starting at zero, incrementing by 1.
202Enumerators with initialization must set \emph{all} enumerators in \emph{ascending} order, \ie there is no auto-initialization.
203\begin{ada}
204type Week is ( Mon, Tue, Wed, Thu, Fri, Sat, Sun );
205        for Week use ( Mon => 0, Tue => 1, Wed => 2, Thu => @10@, Fri => 11, Sat => 14, Sun => 15 );
206\end{ada}
207The enumeration operators are the equality and relational operators, @=@, @/=@, @<@, @<=@, @=@, @/=@, @>=@, @>@, where the ordering relationship is given implicitly by the sequence of ascending enumerators.
208
209Ada provides an alias mechanism, \lstinline[language=ada]{renames}, for aliasing types, which is useful to shorten package identifiers.
210\begin{ada}
211@OtherRed@ : RGB renames Red;
212\end{ada}
213which suggests a possible \CFA extension to @typedef@.
214\begin{cfa}
215typedef RGB.Red OtherRed;
216\end{cfa}
217
218There are three pairs of inverse enumeration pseudo-functions (attributes): @'Pos@ and @'Val@, @'Enum_Rep@ and @'Enum_Val@, and @'Image@ and @'Value@,
219\begin{cquote}
220\setlength{\tabcolsep}{15pt}
221\begin{tabular}{@{}ll@{}}
222\begin{ada}
223RGB'Pos( Red ) = 0;
224RGB'Enum_Rep( Red ) = 10;
225RGB'Image( Red ) = "RED";
226\end{ada}
227&
228\begin{ada}
229RGB'Val( 0 ) = Red
230RGB'Enum_Val( 10 ) =  Red
231RGB'Value( "Red" ) =  Red
232\end{ada}
233\end{tabular}
234\end{cquote}
235These attributes are important for IO.
236An 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.
237
238Ada allows the enumerator label to be a character constant.
239\begin{ada}
240type Operator is ( '+', '-', '*', '/' );
241\end{ada}
242which is syntactic sugar for the label and not character literals from the predefined type @Character@.
243The purpose is strictly readability using character literals rather than identifiers.
244\begin{ada}
245Op : Operator := '+';
246if Op = '+' or else Op = '-' then ... ;
247elsif Op = '*' or else Op = '/' then ... ; end if;
248\end{ada}
249Interestingly, arrays of character enumerators can be treated as strings.
250\begin{ada}
251Ops : array( 0..3 ) of Operator;
252Ops := @"+-*/"@;            -- string assignment to array elements
253Ops := "+-" @&@ "*/";   -- string concatenation and assignment
254\end{ada}
255Ada's @Character@ type is defined as a character enumeration across all Latin-1 characters.
256
257Ada's boolean type is also a special enumeration, which can be used in conditions.
258\begin{ada}
259type Boolean is (False, True); -- False / True not keywords
260@Flag@ : Boolean;
261if @Flag@ then ...    -- conditional
262\end{ada}
263Since only types derived from @Boolean@ can be conditional, @Boolean@ is essentially a builtin type.
264
265Ada provides \emph{consecutive} subsetting of an enumeration using \lstinline[language=ada]{range}.
266\begin{ada}
267type Week is ( Mon, Tue, Wed, Thu, Fri, Sat, Sun );
268subtype Weekday is Week @range Mon .. Fri@;
269subtype Weekend is Week @range Sat .. Sun@;
270Day : Week;
271\end{ada}
272Hence, the ordering of the enumerators is crucial to provide the necessary ranges.
273
274An enumeration type can be used in the Ada \lstinline[language=ada]{case} (all enumerators must appear or a @default@) or iterating constructs.
275\begin{cquote}
276\setlength{\tabcolsep}{15pt}
277\begin{tabular}{@{}ll@{}}
278\begin{ada}
279case Day is
280        when @Mon .. Fri@ => ... ;
281        when @Sat .. Sun@ => ... ;
282end case;
283\end{ada}
284&
285\begin{ada}
286case Day is
287        when @Weekday@ => ... ;  -- subtype ranges
288        when @Weekend@ => ... ;
289end case;
290\end{ada}
291\end{tabular}
292\end{cquote}
293
294\begin{cquote}
295\setlength{\tabcolsep}{12pt}
296\begin{tabular}{@{}lll@{}}
297\begin{ada}
298for Day in @Mon .. Sun@ loop
299        ...
300end loop;
301\end{ada}
302&
303\begin{ada}
304for Day in @Weekday@ loop
305        ...
306end loop;
307\end{ada}
308&
309\begin{ada}
310for Day in @Weekend@ loop
311        ...
312end loop;
313\end{ada}
314\end{tabular}
315\end{cquote}
316
317An enumeration type can be used as an array dimension and subscript.
318\begin{ada}
319Lunch : array( @Week@ ) of Time;
320for Day in Week loop
321        Lunch( @Day@ ) := ... ;       -- set lunch time
322end loop;
323\end{ada}
324
325
326\section{\CC}
327\label{s:C++RelatedWork}
328
329\CC enumeration is largely backward compatible with C, so it inherited C's enumerations with some modifications and additions.
330
331\CC has aliasing using @const@ declarations, like C \see{\VRef{s:Cconst}}, with type inferencing, plus static/dynamic initialization.
332(Note, a \CC @constexpr@ declaration is the same as @const@ with the restriction that the initialization is a compile-time expression.)
333\begin{c++}
334const @auto@ one = 0 + 1;                               $\C{// static initialization}$
335const @auto@ NIL = nullptr;
336const @auto@ PI = 3.14159;
337const @auto@ Plus = '+';
338const @auto@ Fred = "Fred";
339const @auto@ Mon = 0, Tue = Mon + 1, Wed = Tue + 1, Thu = Wed + 1, Fri = Thu + 1,
340                                Sat = Fri + 1, Sun = Sat + 1;
341void foo() {
342        const @auto@ r = random();                      $\C{// dynamic initialization}$
343        int va[r];                                                      $\C{// VLA, auto scope only}$
344}
345\end{c++}
346Statically initialized identifiers may appear in any constant-expression context, \eg @case@.
347Dynamically initialized identifiers may appear as array dimensions in @g++@, which allows variable-sized arrays.
348Interestingly, global \CC @const@ declarations are implicitly marked @static@ (@r@, read-only local, rather than @R@, read-only external)
349\begin{c++}
350$\$$ nm test.o
3510000000000000018 @r@ Mon
352\end{c++}
353whereas C @const@ declarations without @static@ are marked @R@.
354
355The following \CC non-backward compatible change is made~\cite[C.1.5.7.2]{C++}, plus the safe-assignment change shown in~\VRef{s:TypeSafety}.
356\begin{description}[parsep=0pt]
357\item[Change:] In \CC, the type of an enumerator is its enumeration.
358In C, the type of an enumerator is @int@.
359Example:
360\begin{c++}
361enum e { A };
362sizeof(A) == sizeof(int)                                $\C{// in C}$
363sizeof(A) == sizeof(e)                                  $\C{// in \CC}$
364/* and sizeof(int) is not necessary equal to sizeof(e) */
365\end{c++}
366\item[Rationale:] In \CC, an enumeration is a distinct type.
367\item[Effect on original feature:] Change to semantics of well-defined feature.
368\item[Difficulty of converting:] Semantic transformation.
369\item[How widely used:] Seldom. The only time this affects existing C code is when the size of an enumerator is taken.
370Taking the size of an enumerator is not a common C coding practice.
371\end{description}
372Hence, the values in a \CC enumeration can only be its enumerators (without a cast).
373
374While the storage size of an enumerator is up to the compiler, there is still an implicit cast to @int@.
375\begin{c++}
376enum E { A, B, C };
377E e = A;
378int i = A;    i = e;                                    $\C{// implicit casts to int}$
379\end{c++}
380\CC{11} added a scoped enumeration, \lstinline[language=c++]{enum class} (or \lstinline[language=c++]{enum struct})\footnote{
381The use of keyword \lstinline[language=c++]{class} is resonable because default visibility is \lstinline[language=c++]{private} (scoped).
382However, default visibility for \lstinline[language=c++]{struct} is \lstinline[language=c++]{public} (unscoped) making it an odd choice.},
383where the enumerators are accessed using type qualification.
384\begin{c++}
385enum class E { A, B, C };
386E e = @E::@A;                                                   $\C{// qualified enumerator}$
387e = B;                                                                  $\C{// error: B not in scope}$
388\end{c++}
389\CC{20} supports explicit unscoping with a \lstinline[language=c++]{using enum} declaration.
390\begin{c++}
391enum class E { A, B, C };
392@using enum E;@
393E e = A;    e = B;                                              $\C{// direct access}$
394\end{c++}
395\CC{11} added the ability to explicitly declare only an underlying \emph{integral} type for \lstinline[language=c++]{enum class}.
396\begin{c++}
397enum class RGB @: long@ { Red, Green, Blue };
398enum class rgb @: char@ { Red = 'r', Green = 'g', Blue = 'b' };
399enum class srgb @: signed char@ { Red = -1, Green = 0, Blue = 1 };
400\end{c++}
401There is no implicit conversion from the \lstinline[language=c++]{enum class} type to its declared type.
402\begin{c++}
403rgb crgb = rgb::Red;
404char ch = rgb::Red;   ch = crgb;                $\C{// error}$
405\end{c++}
406An enumeration can be used in the @if@ and @switch@ statements.
407\begin{cquote}
408\setlength{\tabcolsep}{15pt}
409\begin{tabular}{@{}ll@{}}
410\begin{c++}
411if ( @day@ <= Fri )
412        cout << "weekday" << endl;
413
414
415
416
417\end{c++}
418&
419\begin{c++}
420switch ( @day@ ) {
421  case Mon: case Tue: case Wed: case Thu: case Fri:
422        cout << "weekday" << endl; break;
423  case Sat: case Sun:
424        cout << "weekend" << endl; break;
425}
426\end{c++}
427\end{tabular}
428\end{cquote}
429However, there is no mechanism to iterate through an enumeration without an unsafe cast and it does not understand the enumerator values.
430\begin{c++}
431enum Week { Mon, Tue, Wed, Thu = 10, Fri, Sat, Sun };
432for ( Week d = Mon; d <= Sun; d = @(Week)(d + 1)@ ) cout << d << ' ';
4330 1 2 @3 4 5 6 7 8 9@ 10 11 12 13
434\end{c++}
435As a consequence, there is no meaningful enumerating mechanism.
436
437An enumeration type cannot declare an array dimension but an enumerator can be used as a subscript.
438There is no mechanism to subset or inherit from an enumeration.
439
440
441\section{C\texorpdfstring{\raisebox{-0.7ex}{\LARGE$^\sharp$}\xspace}{Csharp}} % latex bug: cannot use \relsize{2} so use \LARGE
442\label{s:Csharp}
443
444% https://www.tutorialsteacher.com/codeeditor?cid=cs-mk8Ojx
445% https://learn.microsoft.com/en-us/dotnet/api/system.enum?view=net-8.0
446% https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/enums
447
448\Csharp is a dynamically-typed programming language with a scoped, integral enumeration similar to \CC \lstinline[language=C++]{enum class}.
449\begin{csharp}
450enum Week : @long@ { Mon, Tue, Wed, Thu@ = 10@, Fri, Sat, Sun }
451enum RGB { Red, Green, Blue }
452\end{csharp}
453The default underlying integral type is @int@, with auto-incrementing and implicit/explicit initialization.
454A method cannot be defined in an enumeration type (extension methods are possible).
455There is an explicit bidirectional conversion between an enumeration and its integral type, and an implicit conversion to the enumerator label in display contexts.
456\begin{csharp}
457int iday = (int)Week.Fri;                       $\C{// day == 11}$
458Week day = @(Week)@42;                          $\C{// day == 42, unsafe}$
459string mon = Week.Mon.ToString();       $\C{// mon == "Mon"}$
460RGB rgb = RGB.Red;                                      $\C{// rgb == "Red"}$
461day = @(Week)@rgb;                                      $\C{// day == "Mon", unsafe}$
462Console.WriteLine( Week.Fri );          $\C{// print label Fri}$
463\end{csharp}
464% The majority of the integral operators (relational and arithmetic) work with enumerations, except @*@ and @/@.
465% Relational and arithmetic operators are defined in terms of its numeric value only.
466% Therefore, enumerators are not ordered and not enumerable like \CC.
467Like \CC, \Csharp defines enumeration relational and arithmetic operators in terms of value.
468Enumerators have no defined positional meaning.
469\begin{csharp}
470day = day++ - 5;                                        $\C{// value manipulation}$
471day = day & day;
472\end{csharp}
473\begin{csharp}
474for ( Week d = Mon; d <= Sun; @d += 1@ ) {
475        Console.Write( d + " " );
476}
477Mon Tue Wed @3 4 5 6 7 8 9@ Thu Fri Sat Sun
478\end{csharp}
479As a consequence, there is no direct meaningful enumerating mechanism.
480
481An enumeration can be used in the @if@ and @switch@ statements.
482\begin{cquote}
483\setlength{\tabcolsep}{15pt}
484\begin{tabular}{@{}ll@{}}
485\begin{csharp}
486if ( @day@ <= Week.Fri )
487        Console.WriteLine( "weekday" );
488
489
490
491
492
493\end{csharp}
494&
495\begin{csharp}
496switch ( @day@ ) {
497  case Week.Mon: case Week.Tue: case Week.Wed:
498  case Week.Thu: case Week.Fri:
499        Console.WriteLine( "weekday" ); break;
500  case Week.Sat: case Week.Sun:
501        Console.WriteLine( "weekend" ); break;
502}
503\end{csharp}
504\end{tabular}
505\end{cquote}
506
507To indirectly enumerate, \Csharp's Enum library has @Enum.GetValues@, a pseudo-method that retrieves an array of the enumeration constants for looping over an enumeration type or variable (expensive operation).
508\begin{csharp}
509foreach ( Week d in @Enum.GetValues@( typeof(Week) ) ) {
510        Console.WriteLine( d + " " + (int)d + " " ); // label, position
511}
512Mon 0, Tue 1, Wed 2, Thu 10, Fri 11, Sat 12, Sun 13,
513\end{csharp}
514Hence, enumerating is not supplied directly by the enumeration, but indirectly through the enumerable array type.
515
516An enumeration type cannot declare an array dimension but an enumerator can be used as a subscript.
517There is no mechanism to subset or inherit from an enumeration.
518
519The @Flags@ attribute creates a bit-flags enumeration, making bitwise operators @&@, @|@, @~@ (complement), @^@ (xor) sensible.
520\begin{csharp}
521@[Flags]@ public enum Week {
522        None = 0x0, Mon = 0x1, Tue = 0x2, Wed = 0x4,
523        Thu = 0x8, Fri = 0x10, Sat = 0x20, Sun = 0x40,
524        Weekdays = @Mon | Tue | Wed | Thu | Fri@ $\C{// Weekdays == 0x1f}$
525        Weekend = @Sat | Sun@,                  $\C{// Weekend == 0x60}$
526}
527Week meetings = @Week.Mon | Week.Wed@; $\C{// 0x5}$
528\end{csharp}
529
530
531\section{Go}
532\label{s:Go}
533
534Go has a no enumeration.
535It has @const@ aliasing declarations, similar to \CC \see{\VRef{s:C++RelatedWork}}, for basic types with type inferencing and static initialization (constant expression).
536\begin{Go}
537const R @int@ = 0;  const G @uint@ = 1;  const B = 2; $\C{// explicit typing and type inferencing}$
538const Fred = "Fred";  const Mary = "Mary";  const Jane = "Jane";
539const S = 0;  const T = 0;
540const USA = "USA";  const U = "USA";
541const V = 3.1;  const W = 3.1;
542\end{Go}
543Since these declarations are immutable variables, they are unscoped and Go has no overloading.
544
545Go provides an enumeration-like feature to group together @const@ declaration into a block and introduces a form of auto-initialization.
546\begin{Go}
547const ( R = 0; G; B )                                   $\C{// implicit initialization: 0 0 0}$
548const ( Fred = "Fred"; Mary = "Mary"; Jane = "Jane" ) $\C{// explicit initialization: Fred Mary Jane}$
549const ( S = 0; T; USA = "USA"; U; V = 3.1; W ) $\C{// type change, implicit/explicit: 0 0 USA USA 3.1 3.1}$
550\end{Go}
551The first identifier \emph{must} be explicitly initialized;
552subsequent identifiers can be implicitly or explicitly initialized.
553Implicit initialization is the \emph{previous} (predecessor) identifier value.
554
555Each @const@ declaration provides an implicit integer counter starting at zero, called \lstinline[language=Go]{iota}.
556Using \lstinline[language=Go]{iota} outside of a @const@ block always sets the identifier to zero.
557\begin{Go}
558const R = iota;                                                 $\C{// 0}$
559\end{Go}
560Inside 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.
561\begin{Go}
562const ( R = @iota@; G; B )                              $\C{// implicit: 0 1 2}$
563const ( C = @iota + B + 1@; G; Y )              $\C{// implicit: 3 4 5}$
564\end{Go}
565An underscore \lstinline[language=golang]{const} identifier advances \lstinline[language=Go]{iota}.
566\begin{Go}
567const ( O1 = iota + 1; @_@; O3; @_@; O5 ) // 1, 3, 5 
568\end{Go}
569Auto-initialization reverts from \lstinline[language=Go]{iota} to the previous value after an explicit initialization, but auto-incrementing of \lstinline[language=Go]{iota} continues.
570\begin{Go}
571const ( Mon = iota; Tue; Wed; // 0, 1, 2
572                @Thu = 10@; Fri; Sat; @Sun = itoa@ ) $\C{// 10, 10, 10, {\color{red}6}}$
573\end{Go}
574Auto-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}.
575\begin{Go}
576const ( V1 = iota; V2; @V3 = 7;@ V4 = @iota@ + 1; V5 ) // 0 1 7 4 5
577const ( Mon = iota; Tue; Wed; // 0, 1, 2
578                @Thu = 10;@ Fri = @iota@ - Wed + Thu - 1; Sat; Sun ) // 10, 11, 12, 13
579\end{Go}
580Here, @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}.
581Note, because \lstinline[language=Go]{iota} is incremented for an explicitly initialized identifier or @_@,
582at @Fri@ \lstinline[language=Go]{iota} is 4 requiring the minus one to compute the value for @Fri@.
583
584Basic switch and looping are possible.
585\begin{cquote}
586\setlength{\tabcolsep}{20pt}
587\begin{tabular}{@{}ll@{}}
588\begin{Go}
589day := Mon;     // := $\(\Rightarrow\)$ type inferencing
590switch @day@ {
591  case Mon, Tue, Wed, Thu, Fri:
592        fmt.Println( "weekday" );
593  case Sat, Sun:
594        fmt.Println( "weekend" );
595}
596\end{Go}
597&
598\begin{Go}
599
600for i := @Mon@; i <= @Sun@; i += 1 {
601        fmt.Println( i )
602}
603
604
605
606\end{Go}
607\end{tabular}
608\end{cquote}
609However, the loop prints the values from 0 to 13 because there is no actual enumeration.
610
611A constant variable can be used as an array dimension or a subscript.
612\begin{Go}
613var ar[@Sun@] int
614ar[@Mon@] = 3
615\end{Go}
616
617
618\section{Java}
619
620Java provides an enumeration using a specialized class.
621A basic Java enumeration is an opaque enumeration, where the enumerators are constants.
622\begin{Java}
623enum Week { Mon, Tue, Wed, Thu, Fri, Sat, Sun; }
624Week day = Week.Sat;
625\end{Java}
626The enumerator's members are scoped and cannot be made \lstinline[language=java]{public}, hence requiring qualification.
627The value of an enumeration instance is restricted to its enumerators.
628
629The position (ordinal) and label (name) are accessible but there is no value property.
630\begin{Java}
631System.out.println( day.!ordinal()! + " " + !day! + " " + day.!name()! );
6325 Sat Sat
633\end{Java}
634Since @day@ has no value, it prints its label (name).
635The member @valueOf@ is the inverse of @name@ converting a string to an enumerator.
636\begin{Java}
637day = Week.valueOf( "Wed" );
638\end{Java}
639Extra members can be added to provide specialized operations.
640\begin{Java}
641public boolean isWeekday() { return !ordinal()! <= Fri.ordinal(); }
642public boolean isWeekend() { return Sat.ordinal() <= !ordinal()!; }
643\end{Java}
644Notice the unqualified calls to @ordinal@ in the members implying a \lstinline[language=Java]{this} to some implicit implementation variable, likely an @int@.
645
646Enumerator values require an enumeration type (any Java type may be used) and implementation member.
647\begin{Java}
648enum Week {
649        Mon!(1)!, Tue!(2)!, Wed!(3)!, Thu!(4)!, Fri!(5)!, Sat!(6)!, Sun!(7)!; // must appear first
650        private !long! day;                                     $\C{// enumeration type and implementation member}$
651        private Week( !long! d ) { day = d; } $\C{// enumerator initialization}$
652};
653Week day = Week.Sat;
654\end{Java}
655The position, value, and label are accessible.
656\begin{Java}
657System.out.println( !day.ordinal()! + " " + !day.day! + " " + !day.name()! );
6585 6 Sat
659\end{Java}
660If 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@.
661The implementation constructor must be private since it is only used internally to initialize the enumerators.
662Initialization occurs at the enumeration-type declaration for each enumerator in the first line.
663
664Enumerations can be used in the @if@ and @switch@ statements but only for equality tests.
665\begin{cquote}
666\setlength{\tabcolsep}{15pt}
667\begin{tabular}{@{}ll@{}}
668\begin{Java}
669if ( !day! == Week.Fri )
670        System.out.println( "Fri" );
671
672
673
674
675\end{Java}
676&
677\begin{Java}
678switch ( !day! ) {
679  case Mon: case Tue: case Wed: case Thu: case Fri:
680        System.out.println( "weekday" );  break;
681  case Sat: case Sun:
682        System.out.println( "weekend" );  break;
683}
684\end{Java}
685\end{tabular}
686\end{cquote}
687Notice enumerators in the @switch@ statement do not require qualification.
688
689There 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}.
690Like \Csharp, looping over an enumeration is done using method @values@, which returns an array of enumerator values (expensive operation).
691\begin{Java}
692for ( Week d : Week.values() ) {
693        System.out.print( d.ordinal() + d.day + " " +  d.name() + ",  " );
694}
6950 1 Mon,  1 2 Tue,  2 3 Wed,  3 4 Thu,  4 5 Fri,  5 6 Sat,  6 7 Sun, 
696\end{Java}
697Like \Csharp, enumerating is supplied indirectly through another enumerable type, not via the enumeration.
698
699An enumeration type cannot declare an array dimension nor can an enumerator be used as a subscript.
700Enumeration inheritence is disallowed because an enumeration is \lstinline[language=Java]{final}.
701
702Java 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.
703There is also a specialized version of @HashMap@ with enumerator keys, which has performance benefits.
704
705
706\section{Rust}
707
708% https://doc.rust-lang.org/reference/items/enumerations.html
709
710Rust @enum@ provides two largely independent mechanisms from a single language feature: an ADT and an enumeration.
711When @enum@ is an ADT, pattern matching is used to discriminate among the variant types.
712\begin{cquote}
713\begin{tabular}{@{}l@{\hspace{30pt}}ll@{}}
714\begin{rust}
715struct S {
716        i : isize,  j : isize
717}
718let mut s = S{ i : 3, j : 4 };
719enum @ADT@ {
720        I( isize ), $\C[1in]{// int}$
721        F( f64 ),   $\C{// float}$
722        S( S ),     $\C{// struct}\CRT$
723}
724\end{rust}
725&
726\begin{rust}
727let mut adt : ADT;
728adt = ADT::I(3);  println!( "{:?}", adt );
729adt = ADT::F(3.5);  println!( "{:?}", adt );
730adt = ADT::S(s);  println!( "{:?}", adt );
731@match@ adt {
732        ADT::I( i ) => println!( "{:}", i ),
733        ADT::F( f ) => println!( "{:}", f ),
734        ADT::S( s ) => println!( "{:} {:}", s.i, s.j ),
735}
736\end{rust}
737&
738\begin{rust}
739I(3)
740F(3.5)
741S(S { i: 3, j: 4 })
7423 4
743
744
745
746
747
748\end{rust}
749\end{tabular}
750\end{cquote}
751Even when the variant types are the unit type, the ADT is still not an enumeration because there is no enumerating \see{\VRef{s:AlgebraicDataType}}.
752\begin{rust}
753enum Week { Mon, Tues, Wed, Thu, Fri, Sat, Sun@,@ } // terminating comma
754let mut week : Week = Week::Mon;
755match week {
756        Week::Mon => println!( "Mon" ),
757        ...
758        Week::Sun => println!( "Sun" ),
759}
760\end{rust}
761
762However, Rust allows direct setting of the ADT constructor, which means it is actually a tag.
763\begin{cquote}
764\setlength{\tabcolsep}{15pt}
765\begin{tabular}{@{}ll@{}}
766\begin{rust}
767enum Week {
768        Mon, Tues, Wed, // start 0
769        Thu @= 10@, Fri,
770        Sat, Sun,
771}
772
773\end{rust}
774&
775\begin{rust}
776#[repr(u8)]
777enum ADT {
778        I(isize) @= 5@,
779        F(f64) @= 10@,
780        S(S) @= 0@,
781}
782\end{rust}
783\end{tabular}
784\end{cquote}
785Through 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}.
786When tags represent non-unit types, Rust largely precludes accessing the tag because the semantics become meaningless.
787Hence, the two mechanisms are largely disjoint, and only the enumeration component is discussed.
788
789In detail, the @enum@ type has an implicit integer tag (discriminant) with a unique value for each variant type.
790Direct initialization is achieved by a compile-time expression that generates a constant value.
791Indirect initialization (without initialization, @Fri@/@Sun@) is auto-initialized: from left to right, starting at zero or the next explicitly initialized constant, incrementing by @1@.
792There is an explicit cast from the tag to integer.
793\begin{rust}
794let mut mon : isize = Week::Mon as isize;
795\end{rust}
796An enumeration can be used in the @if@ and \lstinline[language=rust]{match} (@switch@) statements.
797\begin{cquote}
798\setlength{\tabcolsep}{8pt}
799\begin{tabular}{@{}ll@{}}
800\begin{c++}
801if @week as isize@ == Week::Mon as isize {
802        println!( "{:?}", week );
803}
804
805
806\end{c++}
807&
808\begin{c++}
809match @week@ {
810        Week::Mon | Week:: Tue | Week::Wed | Week::Thu
811                | Week::Fri => println!( "weekday" ),
812        Week::Sat | Week:: Sun => println!( "weekend" ),
813}
814\end{c++}
815\end{tabular}
816\end{cquote}
817However, there is no mechanism to iterate through an enumeration without casting to integral and positions versus values is not handled.
818\begin{c++}
819for d in Week::Mon as isize ..= Week::Sun as isize {
820        print!( "{:?} ", d );
821}
8220 1 2 @3 4 5 6 7 8 9@ 10 11 12 13
823\end{c++}
824An enumeration type cannot declare an array dimension nor as a subscript.
825There is no mechanism to subset or inherit from an enumeration.
826
827
828\section{Swift}
829
830% https://www.programiz.com/swift/online-compiler
831
832Like Rust, Swift @enum@ provides two largely independent mechanisms from a single language feature: an ADT and an enumeration.
833When @enum@ is an ADT, pattern matching is used to discriminate among the variant types.
834\begin{cquote}
835\setlength{\tabcolsep}{20pt}
836\begin{tabular}{@{}l@{\hspace{55pt}}ll@{}}
837\begin{swift}
838struct S {
839        var i : Int,  j : Int
840}
841var s = S( i : 3, j : 5 )
842@enum@ ADT {
843        case I(Int)   $\C[1.125in]{// int}$
844        case F(Float) $\C{// float}$
845        case S(S)     $\C{// struct}\CRT$
846}
847\end{swift}
848&
849\begin{swift}
850var adt : ADT
851adt = .I( 3 );  print( adt )
852adt = .F( 3.5 );  print( adt )
853adt = .S( s );  print( adt )
854@switch@ adt {  // pattern matching
855        case .I(let i):  print( i )
856        case .F(let f):  print( f )
857        case .S(let s):  print( s.i, s.j )
858}
859\end{swift}
860&
861\begin{swift}
862I(3)
863F(3.5)
864S(S(i: 3, j: 5))
8653 5
866
867
868
869
870
871\end{swift}
872\end{tabular}
873\end{cquote}
874Note, after an @adt@'s type is know, the enumerator is inferred without qualification, \eg @.I(3)@.
875
876An enumeration is created when \emph{all} the enumerators are unit-type, which is like a scoped, opaque enumeration.
877\begin{swift}
878enum Week { case Mon, Tue, Wed, Thu, Fri, Sat, Sun }; // unit-type
879var week : Week = @Week.Mon@;
880\end{swift}
881As well, it is possible to type \emph{all} the enumerators with a common type, and set different values for each enumerator;
882for integral types, there is auto-incrementing.
883\begin{cquote}
884\setlength{\tabcolsep}{15pt}
885\begin{tabular}{@{}lll@{}}
886\begin{swift}
887enum WeekInt: @Int@ {
888        case Mon, Tue, Wed, Thu = 10, Fri,
889                        Sat = 4, Sun // auto-incrementing
890};
891\end{swift}
892&
893\begin{swift}
894enum WeekStr: @String@ {
895        case Mon = "MON", Tue, Wed, Thu, Fri,
896                        Sat = "SAT", Sun
897};
898\end{swift}
899\end{tabular}
900\end{cquote}
901An enumeration only supports equality comparison between enumerator values, unless it inherits from @Comparable@, adding relational operators @<@, @<=@, @>@, and @>=@.
902
903An enumeration can have methods.
904\begin{swift}
905enum Week: @Comparable@ {
906        case Mon, Tue, Wed, Thu, Fri, Sat, Sun // unit-type
907        func @isWeekday() -> Bool@ { return self <= .Fri }  // methods
908        func @isWeekend() -> Bool@ { return .Sat <= self }
909};
910\end{swift}
911An enumeration can be used in the @if@ and @switch@ statements, where @switch@ must be exhaustive or have a @default@.
912\begin{cquote}
913\setlength{\tabcolsep}{15pt}
914\begin{tabular}{@{}ll@{}}
915\begin{swift}
916if @week <= .Fri@ {
917        print( "weekday" );
918}
919
920
921\end{swift}
922&
923\begin{swift}
924switch @week@ {
925        case .Mon: print( "Mon" )
926        ...
927        case .Sun: print( "Sun" )
928}
929\end{swift}
930\end{tabular}
931\end{cquote}
932Enumerating is accomplished by inheriting from @CaseIterable@ without any associated values.
933\begin{swift}
934enum Week: Comparable, @CaseIterable@ {
935        case Mon, Tue, Wed, Thu, Fri, Sat, Sun // unit-type
936};
937for day in Week@.allCases@ {
938        print( day, terminator:" " ) 
939}
940Mon Tue Wed Thu Fri Sat Sun
941\end{swift}
942The @enum.allCases@ property returns a collection of all the cases for looping over an enumeration type or variable (expensive operation).
943
944A typed enumeration is accomplished by inheriting from any Swift type, and accessing the underlying enumerator value is done with the attribute @rawValue@.
945Type @Int@ has auto-incrementing from the previous enumerator;
946type @String@ has auto-incrementing of the enumerator label.
947\begin{cquote}
948\setlength{\tabcolsep}{15pt}
949\begin{tabular}{@{}lll@{}}
950\begin{swift}
951enum WeekInt: @Int@, CaseIterable {
952        case Mon, Tue, Wed, Thu = 10, Fri,
953                        Sat = 4, Sun // auto-incrementing
954};
955for day in WeekInt.allCases {
956        print( day@.rawValue@, terminator:" " ) 
957}
9580 1 2 10 11 4 5 
959\end{swift}
960&
961\begin{swift}
962enum WeekStr: @String@, CaseIterable {
963        case Mon = "MON", Tue, Wed, Thu, Fri,
964                        Sat = "SAT", Sun
965};
966for day in WeekStr.allCases {
967        print( day@.rawValue@, terminator:" " ) 
968}
969MON Tue Wed Thu Fri SAT Sun
970\end{swift}
971\end{tabular}
972\end{cquote}
973
974There is a bidirectional conversion from typed enumerator to @rawValue@ and vice versa.
975\begin{swift}
976var weekInt : WeekInt = WeekInt.Mon;
977if let opt = WeekInt( rawValue: 0 ) {  // test optional return value
978        print( weekInt.rawValue, opt )  // 0 Mon
979} else {
980        print( "invalid weekday lookup" )
981}
982\end{swift}
983Conversion from @rawValue@ to enumerator may fail (bad lookup), so the result is an optional value.
984
985
986\section{Python 3.13}
987% https://docs.python.org/3/howto/enum.html
988
989Python is a dynamically-typed reflexive programming language with multiple incompatible versions.
990The generality of the language makes it possible to extend existing or build new language features.
991As 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.
992Therefore, the following discussion is (mostly) restricted to the core enumeration features in Python 3.13.
993
994A Python enumeration is not a basic type;
995it is a @class@ inheriting from the @Enum@ class.
996The @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.
997Hence, an enumeration instance is a fixed type (enumeration pair), and its value is the type of one of the enumerator pairs.
998
999The enumerator value fields must be explicitly initialized and be \emph{unique}.
1000\begin{python}
1001class Week(!Enum!): Mon = 1; Tue = 2; Wed = 3; Thu = 4; Fri = 5; Sat = 6; Sun = 7
1002\end{python}
1003and/or explicitly auto-initialized, \eg:
1004\begin{python}
1005class Week(Enum): Mon = 1; Tue = 2; Wed = 3; Thu = 10; Fri = !auto()!; Sat = 4; Sun = !auto()!
1006Mon : 1 Tue : 2 Wed : 3 Thu : 10 Fri : !11! Sat : 4 Sun : !12!
1007\end{python}
1008where @auto@ increments by 1 from the previous @auto@ value \see{Go \lstinline[language=Go]{iota}, \VRef{s:Go}}.
1009@auto@ is controlled by member @_generate_next_value_()@, which can be overridden:
1010\begin{python}
1011@staticmethod
1012def _generate_next_value_( name, start, count, last_values ):
1013        return name
1014\end{python}
1015
1016There is no direct concept of restricting the enumerators in an enumeration \emph{instance} because dynamic typing changes the type.
1017\begin{python}
1018class RGB(Enum): Red = 1; Green = 2; Blue = 3
1019day : Week = Week.Tue;          $\C{\# type is Week}$
1020!day = RGB.Red!                         $\C{\# type is RGB}$
1021!day : Week = RGB.Red!          $\C{\# type is RGB}$
1022\end{python}
1023The enumerators are constants and cannot be reassigned.
1024Hence, while enumerators can be different types,
1025\begin{python}
1026class Diff(Enum): Int = 1; Float = 3.5; Str = "ABC"
1027\end{python}
1028it is not an ADT because the enumerator names are not constructors.
1029
1030An enumerator initialized with the same value is an alias and invisible at the enumeration level, \ie the alias is substituted for its aliasee.
1031\begin{python}
1032class WeekD(Enum): Mon = 1; Tue = 2; Wed = 3; Thu = !10!; Fri = !10!; Sat = !10!; Sun = !10!
1033\end{python}
1034Here, the enumeration has only 4 enumerators and 3 aliases.
1035An alias is only visible by dropping down to the @class@ level and asking for class members.
1036Aliasing is prevented using the @unique@ decorator.
1037\begin{python}
1038!@unique!
1039class DupVal(Enum): One = 1; Two = 2; Three = !3!; Four = !3!
1040ValueError: duplicate values found in <enum 'DupVal'>: Four -> Three
1041\end{python}
1042
1043\begin{lrbox}{\myboxA}
1044\begin{python}
1045def by_position(enum_type, position):
1046        for index, value in enumerate(enum_type):
1047                if position == index: return value
1048        raise Exception("by_position out of range")
1049\end{python}
1050\end{lrbox}
1051There are bidirectional enumeration pseudo-functions for label and value, but there is no concept of access using ordering (position).\footnote{
1052There is an $O(N)$ mechanism to access an enumerator's value by position. \newline \usebox\myboxA}
1053\begin{cquote}
1054\setlength{\tabcolsep}{15pt}
1055\begin{tabular}{@{}ll@{}}
1056\begin{python}
1057Week.Thu.value == 4;
1058Week.Thu.name == "Thu";
1059\end{python}
1060&
1061\begin{python}
1062Week( 4 ) == Week.Thu
1063Week["Thu"].value == 4
1064\end{python}
1065\end{tabular}
1066\end{cquote}
1067@Enum@ only supports equality comparison between enumerator values.
1068There are multiple library extensions to @Enum@, \eg @OrderedEnum@ recipe class, adding relational operators @<@, @<=@, @>@, and @>=@.
1069
1070An enumeration \lstinline[language=python]{class} can have methods.
1071\begin{python}
1072class Week(!OrderedEnum!):
1073        Mon = 1; Tue = 2; Wed = 3; Thu = 4; Fri = 5; Sat = 6; Sun = 7
1074        def !isWeekday(self)!:          # methods
1075                return Week(self.value) !<=! Week.Fri
1076        def !isWeekend(self)!:
1077                return Week.Sat !<=! Week(self.value) 
1078\end{python}
1079
1080An enumeration can be used in the @if@ and @switch@ statements but only for equality tests, unless extended to @OrderedEnum@.
1081\begin{cquote}
1082\setlength{\tabcolsep}{12pt}
1083\begin{tabular}{@{}ll@{}}
1084\begin{python}
1085if day <= Week.Fri :
1086        print( "weekday" );
1087
1088
1089
1090\end{python}
1091&
1092\begin{python}
1093match day:
1094        case Week.Mon | Week.Tue | Week.Wed | Week.Thu | Week.Fri:
1095                print( "weekday" );
1096        case Week.Sat | Week.Sun:
1097                print( "weekend" );
1098\end{python}
1099\end{tabular}
1100\end{cquote}
1101Looping is performed using the enumeration type or @islice@ from @itertools@ based on position.
1102\begin{python}
1103for day in !Week!:                                      $\C[2.25in]{\# Mon : 1 Tue : 2 Wed : 3 Thu : 4 Fri : 5 Sat : 6 Sun : 7}$
1104        print( day.name, ":", day.value, end=" " )
1105for day in !islice(Week, 0, 5)!:        $\C{\# Mon : 1 Tue : 2 Wed : 3 Thu : 4 Fri : 5}$
1106        print( day.name, ":", day.value, end=" " )
1107for day in !islice(Week, 5, 7)!:        $\C{\# Sat : 6 Sun : 7}$
1108        print( day.name, ":", day.value, end=" " )
1109for day in !islice(Week,0, 7, 2)!:      $\C{\# Mon : 1 Wed : 3 Fri : 5 Sun : 7}\CRT$
1110        print( day.name, ":", day.value, end=" " )
1111\end{python}
1112Iterating that includes alias names only (strings) is done using attribute @__members__@.
1113\begin{python}
1114for day in WeekD.__members__:
1115        print( day, ":", end=" " )
1116Mon : Tue : Wed : Thu : Fri : Sat : Sun
1117\end{python}
1118
1119Enumeration subclassing is allowed only if the enumeration base-class does not define any members.
1120\begin{python}
1121class WeekE(OrderedEnum): !pass!;  # no members
1122class WeekDay(WeekE): Mon = 1; Tue = 2; Wed = 3; Thu = 4; Fri = 5;
1123class WeekEnd(WeekE): Sat = 6; Sun = 7
1124\end{python}
1125Here, type @WeekE@ is an abstract type because dynamic typing never uses it.
1126\begin{cquote}
1127\setlength{\tabcolsep}{25pt}
1128\begin{tabular}{@{}ll@{}}
1129\begin{python}
1130print( type(WeekE) )
1131day : WeekE = WeekDay.Fri       # set type
1132print( type(day), day )
1133day = WeekEnd.Sat                           # set type
1134print( type(day), day )
1135\end{python}
1136&
1137\begin{python}
1138<$class$ 'enum.EnumType'>
1139
1140<enum 'WeekDay'> WeekDay.Fri
1141
1142<enum 'WeekEnd'> WeekEnd.Sat
1143\end{python}
1144\end{tabular}
1145\end{cquote}
1146
1147There are a number of supplied enumeration base-types: @IntEnum@, @StrEnum@, @IntFalg@, @Flag@, which restrict the values in an enum using multi-inheritance.
1148@IntEnum@ is a subclass of @int@ and @Enum@, allowing enumerator comparison to @int@ and other enumerators of this type (like C enumerators).
1149@StrEnum@ is the same as @IntEnum@ but a subclass of the string type \lstinline[language=python]{str}.
1150@IntFlag@, is a restricted subclass of @int@ where the enumerators can be combined using the bitwise operators (@&@, @|@, @^@, @~@) and the result is an @IntFlag@ member.
1151@Flag@ is the same as @IntFlag@ but cannot be combined with, nor compared against, any other @Flag@ enumeration, nor @int@.
1152Auto increment for @IntFlag@ and @Flag@ is by powers of 2.
1153Enumerators that are combinations of single-bit enumerators are aliases and, hence, invisible.
1154The following is an example for @Flag@.
1155\begin{python}
1156class WeekF(Flag): Mon = 1; Tue = 2; Wed = 4; Thu = !auto()!; Fri = 16; Sat = 32; Sun = 64; \
1157          Weekday = Mon | Tue | Wed | Thu | Fri; \
1158          Weekend = Sat | Sun
1159print( f"0x{repr(WeekF.Weekday.value)} 0x{repr(WeekF.Weekend.value)}" )
11600x31 0x96
1161\end{python}
1162It is possible to enumerate through a @Flag@ enumerator (no aliases):
1163\begin{python}
1164for day in WeekF:
1165        print( f"{day.name}: {day.value}", end=" ")
1166Mon: 1 Tue: 2 Wed: 4 Thu: 8 Fri: 16 Sat: 32 Sun: 64 
1167\end{python}
1168and a combined alias enumerator for @Flag@.
1169\begin{cquote}
1170\setlength{\tabcolsep}{15pt}
1171\begin{tabular}{@{}ll@{}}
1172\begin{python}
1173weekday = WeekF.Weekday
1174for day in weekday:
1175        print( f"{day.name}:"
1176                   f" {day.value}", end=" " )
1177Mon: 1 Tue: 2 Wed: 4 Thu: 8 Fri: 16 
1178\end{python}
1179&
1180\begin{python}
1181weekend = WeekF.Weekend
1182for day in weekend:
1183        print( f"{day.name}:"
1184                   f" {day.value}", end=" " )
1185Sat: 32 Sun: 64 
1186\end{python}
1187\end{tabular}
1188\end{cquote}
1189
1190
1191\section{OCaml}
1192
1193% https://ocaml.org/docs/basic-data-types#enumerated-data-types
1194% https://dev.realworldocaml.org/runtime-memory-layout.html
1195
1196Like Haskell, OCaml @enum@ provides two largely independent mechanisms from a single language feature: an ADT and an enumeration.
1197When @enum@ is an ADT, pattern matching is used to discriminate among the variant types.
1198\begin{cquote}
1199\setlength{\tabcolsep}{20pt}
1200\begin{tabular}{@{}l@{\hspace{35pt}}ll@{}}
1201\begin{ocaml}
1202type s = { i : int; j : int }
1203let sv : s = { i = 3; j = 5 }
1204@type@ adt =
1205        I of int |    $\C[1in]{// int}$
1206        F of float |  $\C{// float}$
1207        S of s        $\C{// struct}\CRT$
1208
1209
1210\end{ocaml}
1211&
1212\begin{ocaml}
1213let adtprt( adtv : adt ) =
1214        @match@ adtv with (* pattern matching *)
1215                I i -> printf "%d\n" i |
1216                F f -> printf "%g\n" f |
1217                S sv -> printf "%d %d\n" sv.i sv.j
1218let adtv : adt = I(3)       let _ = adtprt( adtv )
1219let adtv : adt = F(3.5)   let _ = adtprt( adtv )
1220let adtv : adt = S(sv)    let _ = adtprt( adtv )
1221\end{ocaml}
1222&
1223\begin{ocaml}
12243
12253.5
12263 5
1227
1228
1229
1230
1231
1232\end{ocaml}
1233\end{tabular}
1234\end{cquote}
1235(Note, after an @adtv@'s type is know, the enumerator is inferred without qualification, \eg @I(3)@.)
1236The type names are independent of the type value and mapped to an opaque, ascending, integral tag, starting from 0, supporting relational operators @<@, @<=@, @>@, and @>=@.
1237\begin{cquote}
1238\setlength{\tabcolsep}{10pt}
1239\begin{tabular}{@{}l@{\hspace{25pt}}ll@{}}
1240\begin{ocaml}
1241let silly( adtv : adt ) =
1242        if adtv <= F(3.5) then
1243                printf "<= F\n"
1244        else if adtv >= S(sv) then
1245                printf ">= S\n"
1246\end{ocaml}
1247&
1248\begin{ocaml}
1249let adtv : adt = I(3)       let _ = silly( adtv )
1250let adtv : adt = F(3.5)   let _ = silly( adtv )
1251let adtv : adt = S(sv)    let _ = silly( adtv )
1252
1253
1254\end{ocaml}
1255&
1256\begin{ocaml}
1257<= F
1258<= F
1259>= S
1260
1261
1262\end{ocaml}
1263\end{tabular}
1264\end{cquote}
1265In the example, type values must be specified (any appropriate values work) but ignored in the relational comparison of the type tag.
1266
1267An 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.
1268\begin{ocaml}
1269type week = Mon | Tue | Wed | Thu | Fri | Sat | Sun
1270let day : week = Mon
1271\end{ocaml}
1272Since the type names are opaque, a type-tag value cannot be explicitly set nor can it have a type other than integral.
1273
1274As 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.
1275
1276While OCaml enumerators have an ordering following the definition order, they are not enumerable.
1277To iterate over all enumerators, an OCaml type needs to derive from the @enumerate@ preprocessor, which appends a list of all enumerators to the program abstract syntax tree (AST).
1278However, the list of values may not persist in the defined ordering.
1279As a consequence, there is no meaningful enumerating mechanism.
1280
1281Enumeration subsetting is allowed but inheritance is restricted to classes not types.
1282\begin{ocaml}
1283type weekday = Mon | Tue | Wed | Thu | Fri
1284type weekend = Sat | Sun
1285type week = Weekday of weekday | Weekend of weekend
1286let day : week = Weekend Sun
1287\end{ocaml}
1288
1289%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1290
1291\begin{comment}
1292Date: Wed, 13 Mar 2024 10:52:34 -0400
1293Subject: Re: OCaml
1294To: "Peter A. Buhr" <pabuhr@uwaterloo.ca>
1295From: Gregor Richards <gregor.richards@uwaterloo.ca>
1296
1297On 3/12/24 18:34, Peter A. Buhr wrote:
1298> Gregor, attached is a section Jiada wrote on OCaml (1-page).
1299> Does it reflect our discussion about functional languages and enumerations?
1300
1301Yeah, I think so. The most important part, i.e., that once they're
1302parameterized they're not really enumerations at all, is covered clearly
1303enough.
1304
1305A couple quibbles:
1306
1307<<a list of untyped tags>>
1308
1309This is true, but leaking implementation details. These are nullary datatype
1310constructors. Indeed, you later talk about "tagged variants", which are really
1311just parameterized variants, using the term "tag" differently, confusing the
1312term "tag" further.
1313
1314<<Because week is a summation of values Mon to Sun, it is a sum type in
1315turns of the functional-programming paradigm>>
1316
1317It is a *union* of values and is a *union* type.
1318
1319With valediction,
1320  - Gregor Richards
1321
1322
1323Date: Thu, 14 Mar 2024 21:45:52 -0400
1324Subject: Re: OCaml "enums" do come with ordering
1325To: "Peter A. Buhr" <pabuhr@uwaterloo.ca>
1326From: Gregor Richards <gregor.richards@uwaterloo.ca>
1327
1328On 3/14/24 21:30, Peter A. Buhr wrote:
1329> I've marked 3 places with your name to shows places with enum ordering.
1330>
1331> open Printf
1332> type week = Mon | Tue | Wed | Thu | Fri | Sat | Sun
1333> let day : week = Mon
1334> let take_class( d : week ) =
1335>       if d <= Fri then                                (* Gregor *)
1336>               printf "week\n"
1337>       else if d >= Sat then                   (* Gregor *)
1338>               printf "weekend\n";
1339>       match d with
1340>               Mon | Wed -> printf "CS442\n" |
1341>               Tue | Thu -> printf "CS343\n" |
1342>               Fri -> printf "Tutorial\n" |
1343>               _ -> printf "Take a break\n"
1344>
1345> let _ = take_class( Mon ); take_class( Sat );
1346>
1347> type colour = Red | Green of string | Blue of int * float
1348> let c = Red
1349> let _ = match c with Red -> printf "Red, "
1350> let c = Green( "abc" )
1351> let _ = match c with Green g -> printf "%s, " g
1352> let c = Blue( 1, 1.5 )
1353> let _ = match c with Blue( i, f ) -> printf "%d %g\n" i f
1354>
1355> let check_colour(c: colour): string =
1356>       if c < Green( "xyz" ) then              (* Gregor *)
1357>               printf "green\n";
1358>       match c with
1359>               Red -> "Red" |
1360>               Green g -> g |
1361>               Blue(i, f) -> string_of_int i ^ string_of_float f
1362> let _ = check_colour( Red ); check_colour( Green( "xyz" ) );
1363>
1364> type stringList = Empty | Pair of string * stringList
1365> let rec len_of_string_list(l: stringList): int =
1366>       match l with
1367>               Empty -> 0 |
1368>               Pair(_ , r) -> 1 + len_of_string_list r
1369>
1370> let _ = for i = 1 to 10 do
1371>       printf "%d, " i
1372> done
1373>
1374> (* Local Variables: *)
1375> (* tab-width: 4 *)
1376> (* compile-command: "ocaml test.ml" *)
1377> (* End: *)
1378
1379My functional-language familiarity is far more with Haskell than OCaml.  I
1380mostly view OCaml through a lens of "it's Haskell but with cheating".  Haskell
1381"enums" (ADTs) aren't ordered unless you specifically and manually put them in
1382the Ord typeclass by defining the comparators.  Apparently, OCaml has some
1383other rule, which I would guess is something like "sort by tag then by order of
1384parameter". Having a default behavior for comparators is *bizarre*; my guess
1385would be that it gained this behavior in its flirtation with object
1386orientation, but that's just a guess (and irrelevant).
1387
1388This gives a total order, but not enumerability (which would still be
1389effectively impossible or even meaningless since enums are just a special case
1390of ADTs).
1391
1392With valediction,
1393  - Gregor Richards
1394
1395Date: Wed, 20 Mar 2024 18:16:44 -0400
1396Subject: Re:
1397To: "Peter A. Buhr" <pabuhr@uwaterloo.ca>
1398From: Gregor Richards <gregor.richards@uwaterloo.ca>
1399
1400
1401On 3/20/24 17:26, Peter A. Buhr wrote:
1402> Gregor, everyone at this end would like a definition of "enumerability". Can
1403> you formulate one?
1404
1405According to the OED (emphasis added to the meaning I'm after):
1406
1407enumerate (verb, transitive). To count, ascertain the number of; **more
1408usually, to mention (a number of things or persons) separately, as if for the
1409purpose of counting**; to specify as in a list or catalogue.
1410
1411With C enums, if you know the lowest and highest value, you can simply loop
1412over them in a for loop (this is, of course, why so many enums come with an
1413ENUM_WHATEVER_LAST value). But, I would be hesitant to use the word "loop" to
1414describe enumerability, since in functional languages, you would recurse for
1415such a purpose.
1416
1417In Haskell, in order to do something with every member of an "enumeration", you
1418would have to explicitly list them all. The type system will help a bit since
1419it knows if you haven't listed them all, but you would have to statically have
1420every element in the enumeration.  If somebody added new elements to the
1421enumeration later, your code to enumerate over them would no longer work
1422correctly, because you can't simply say "for each member of this enumeration do
1423X". In Haskell that's because there aren't actually enumerations; what they use
1424as enumerations are a degenerate form of algebraic datatypes, and ADTs are
1425certainly not enumerable. In OCaml, you've demonstrated that they impose
1426comparability, but I would still assume that you can't make a loop over every
1427member of an enumeration. (But, who knows!)
1428
1429Since that's literally what "enumerate" means, it seems like a rather important
1430property for enumerations to have ;)
1431
1432With valediction,
1433  - Gregor Richards
1434
1435
1436From: Andrew James Beach <ajbeach@uwaterloo.ca>
1437To: Gregor Richards <gregor.richards@uwaterloo.ca>, Peter Buhr <pabuhr@uwaterloo.ca>
1438CC: Michael Leslie Brooks <mlbrooks@uwaterloo.ca>, Fangren Yu <f37yu@uwaterloo.ca>,
1439        Jiada Liang <j82liang@uwaterloo.ca>
1440Subject: Re: Re:
1441Date: Thu, 21 Mar 2024 14:26:36 +0000
1442
1443Does this mean that not all enum declarations in C create enumerations? If you
1444declare an enumeration like:
1445
1446enum Example {
1447        Label,
1448        Name = 10,
1449        Tag = 3,
1450};
1451
1452I don't think there is any way to enumerate (iterate, loop, recurse) over these
1453values without listing all of them.
1454
1455
1456Date: Thu, 21 Mar 2024 10:31:49 -0400
1457Subject: Re:
1458To: Andrew James Beach <ajbeach@uwaterloo.ca>, Peter Buhr <pabuhr@uwaterloo.ca>
1459CC: Michael Leslie Brooks <mlbrooks@uwaterloo.ca>, Fangren Yu <f37yu@uwaterloo.ca>,
1460    Jiada Liang <j82liang@uwaterloo.ca>
1461From: Gregor Richards <gregor.richards@uwaterloo.ca>
1462
1463I consider this conclusion reasonable. C enums can be nothing more than const
1464ints, and if used in that way, I personally wouldn't consider them as
1465enumerations in any meaningful sense, particularly since the type checker
1466essentially does nothing for you there. Then they're a way of writing consts
1467repeatedly with some textual indicator that these definitions are related; more
1468namespace, less enum.
1469
1470When somebody writes bitfield members as an enum, is that *really* an
1471enumeration, or just a use of the syntax for enums to keep related definitions
1472together?
1473
1474With valediction,
1475  - Gregor Richards
1476
1477
1478Date: Tue, 16 Apr 2024 11:04:51 -0400
1479Subject: Re: C unnamed enumeration
1480To: "Peter A. Buhr" <pabuhr@uwaterloo.ca>
1481CC: <ajbeach@uwaterloo.ca>, <j82liang@uwaterloo.ca>, <mlbrooks@uwaterloo.ca>,
1482        <f37yu@uwaterloo.ca>
1483From: Gregor Richards <gregor.richards@uwaterloo.ca>
1484
1485On 4/16/24 09:55, Peter A. Buhr wrote:
1486> So what is a variant? Is it a set of tag names, which might be a union or is it
1487> a union, which might have tag names?
1488
1489Your tagless variant bears no resemblance to variants in any functional
1490programming language. A variant is a tag AND a union. You might not need to put
1491anything in the union, in which case it's a pointless union, but the named tag
1492is absolutely mandatory. That's the thing that varies.
1493
1494I was unaware of std::variant. As far as functional languages are concerned,
1495std::variant IS NOT A VARIANT. Perhaps it would be best to use the term ADT for
1496the functional language concept, because that term has no other meanings.
1497
1498An ADT cannot not have a named tag. That's meaningless. The tag is the data
1499constructor, which is the thing you actually define when you define an ADT. It
1500is strictly the union that's optional.
1501
1502With valediction,
1503  - Gregor Richards
1504\end{comment}
1505
1506
1507\section{Comparison}
1508
1509\VRef[Table]{t:FeatureLanguageComparison} shows a comparison of enumeration features and programming languages with the explaination of categories below.
1510The features are high-level and may not capture nuances within a particular language.
1511
1512\begin{table}
1513\caption{Enumeration Feature / Language Comparison}
1514\label{t:FeatureLanguageComparison}
1515\small
1516\setlength{\tabcolsep}{3pt}
1517\newcommand{\CM}{\checkmark}
1518\begin{tabular}{r|c|c|c|c|c|c|c|c|c|c|c|c|c}
1519                                &Pascal & Ada                   &\Csharp   & OCaml  & Java      &Golang   & Rust                & Swift                 & Python& C             & \CC   & \CFA  \\
1520\hline
1521enum                    &Dialect& \CM                   & \CM      & ADT    & \CM   & @const@ &ADT/\CM      &ADT/\CM            & \CM   &\CM    &\CM   &\CM\\
1522\hline
1523\hline
1524opaque                  & \CM    &                              &                  & \CM    & \CM   &             & \CM         & \CM                   &               &               &               & \CM   \\
1525\hline
1526typed                   & Int    & Int                  & Integral  & H     & U     & H       & U/H         & U/H           & H     & Int       & Integral& U   \\
1527\hline
1528safety          & \CM   & \CM                   &          & \CM        & \CM   &                 & \CM                 & \CM                   &               &               & \CM   & \CM   \\
1529\hline
1530posn ordered    & Implied & Implied     &          & \CM    &       &             &                         &                   &       &           &       & \CM       \\
1531\hline
1532unique values   & \CM   & \CM           &           &           &       &      &                            & \CM               &       &           &       &     \\
1533\hline
1534auto-init               & \CM   & all or none   & \CM      &      &       & \CM     & \CM           & \CM               & \CM   & \CM   & \CM   & \CM   \\
1535\hline
1536(Un)Scoped              & U     & U                     & S        & S      & S         & U       & S               & S                         & S     & U             & U/S   & U/S   \\
1537\hline
1538overload                &               & \CM                   &              &            &      &              &                 &                       &      &            &       & \CM   \\
1539\hline
1540loop                    & \CM   & \CM                   &                  &            &               &                 &                         &                   & \CM   &               &               & \CM   \\
1541\hline
1542arr. dim.               & \CM   & \CM           &                  &              &                 &           &                 &                         &            &      &               & \CM \\
1543\hline
1544subset                  & \CM   & \CM                   &         & \CM     &           &                 &                         &                   &               &               &               & \CM   \\
1545\hline
1546superset                &               &                               &                 &                 &           &                 &                         &               &           &               &               & \CM   \\
1547\end{tabular}
1548\end{table}
1549
1550\begin{enumerate}
1551\item opaque: an enumerator cannot be used as its underlying representation or implemented in terms of an ADT.
1552\item typed: H $\Rightarrow$ heterogeneous, \ie enumerator values may be different types. \\
1553U $\Rightarrow$ homogenous, \ie enumerator values have the same type.
1554\item safety: An enumeration variable can only hold a value from its defined enumerators.
1555\item posn ordered: enumerators have defined ordering based on enumerator declaration order.
1556Position ordered is implied if the enumerator values must be strictly increasingly.
1557\item unique value: enumerators must have a unique value.
1558\item auto-init: Values are auto-initializable by language specification, often being "+1" of the predecessor.
1559\item (Un)Scoped: U $\Rightarrow$ enumerators are projected into the containing scope.
1560S $\Rightarrow$ enumerators are contained in the enumeration scope and require qualification.
1561\item overload: An enumerator label can be used without type qualification in a context where multiple enumerations have defined the label.
1562\item loop: Enumerate without the need to convert an enumeration to another data structure.
1563\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).
1564\item subset: Name a subset of enumerators as a new type.
1565\item superset: Create a new enumeration that contains all enumerators from pre-defined enumerations.
1566\end{enumerate}
Note: See TracBrowser for help on using the repository browser.