source: doc/theses/jiada_liang_MMath/relatedwork.tex @ 11cced6

Last change on this file since 11cced6 was 11cced6, checked in by JiadaL <j82liang@…>, 2 months ago

grammar update and section moved

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