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

Last change on this file since 1725989 was c033405, checked in by Peter A. Buhr <pabuhr@…>, 3 weeks ago

first complete proofread of related-work chapter, still needs harmonizing across languages

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