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

Last change on this file since c40a982 was d96d4f0, checked in by Peter A. Buhr <pabuhr@…>, 5 months ago

corrections to Pascal discussion

  • Property mode set to 100644
File size: 55.7 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
24\section{Pascal}
25\label{s:Pascal}
26
27Pascal introduced the \lstinline[language=Pascal]{const} aliasing declaration binding a name to a constant literal/expression.
28\begin{pascal}
29const Three = 2 + 1;   NULL = NIL;   PI = 3.14159;   Plus = '+';   Fred = 'Fred';
30\end{pascal}
31As stated, this mechanism is not an enumeration because there is no specific type (pseudo enumeration).
32Hence, there is no notion of a (possibly ordered) set.
33The type of each constant name (enumerator) is inferred from the constant-expression type.
34
35Pascal introduced the enumeration type characterized by a set of ordered, unscoped identifiers (enumerators), which are not overloadable.\footnote{%
36Pascal is \emph{case-insensitive} so identifiers may appear in multiple forms and still be the same, \eg \lstinline{Mon}, \lstinline{moN}, and \lstinline{MON} (a questionable design decision).}
37\begin{pascal}
38type Week = ( Mon, Tue, Wed, Thu, Fri, Sat, Sun );
39\end{pascal}
40Object initialization and assignment are restricted to the enumerators of this type.
41Enumerators are auto-initialized from left to right, starting at zero, 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 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}
79There should be a static/dynamic range check to verify 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, subtype @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, like C, 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 assignmente 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 acsending 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 a conditional, @Boolean@ is essentially  a builtin 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 backwards 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}
440However, there is no mechanism to iterate through an enumeration without an unsafe cast and it does not understand the enumerator values.
441\begin{c++}
442enum Week { Mon, Tue, Wed, Thu = 10, Fri, Sat, Sun };
443for ( Week d = Mon; d <= Sun; d = @(Week)(d + 1)@ ) cout << d << ' ';
4440 1 2 @3 4 5 6 7 8 9@ 10 11 12 13
445\end{c++}
446An enumeration type cannot declare an array dimension but an enumerator can be used as a subscript.
447There is no mechanism to subtype or inherit from an enumeration.
448
449
450\section{C\raisebox{-0.7ex}{\LARGE$^\sharp$}\xspace} % latex bug: cannot use \relsize{2} so use \LARGE
451\label{s:Csharp}
452
453% https://www.tutorialsteacher.com/codeeditor?cid=cs-mk8Ojx
454% https://learn.microsoft.com/en-us/dotnet/api/system.enum?view=net-8.0
455% https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/enums
456
457\Csharp is a dynamically-typed programming-language with a scoped, integral enumeration similar to \CC \lstinline[language=C++]{enum class}.
458\begin{csharp}
459enum Week : @long@ { Mon, Tue, Wed, Thu@ = 10@, Fri, Sat, Sun@,@ } // terminating comma
460enum RGB { Red, Green, Blue }
461\end{csharp}
462The default underlying integral type is @int@ (no @char@), with auto-incrementing, implicit/explicit initialization, and terminating comma.
463A method cannot be defined in an enumeration type (extension methods are possible).
464There is an explicit bidirectional conversion between an enumeration and its integral type, and an implicit conversion to the enumerator label in display contexts.
465\begin{csharp}
466int iday = (int)Week.Fri;                       $\C{// day == 11}$
467Week day = @(Week)@42;                          $\C{// day == 42, unsafe}$
468string mon = Week.Mon.ToString();       $\C{// mon == "Mon"}$
469RGB rgb = RGB.Red;                                      $\C{// rgb == "Red"}$
470day = @(Week)@rgb;                                      $\C{// day == "Mon", unsafe}$
471Console.WriteLine( Week.Fri );          $\C{// print label Fri}$
472\end{csharp}
473The majority of the integral operators (relational and arithmetic) work with enumerations, except @*@ and @/@.
474\begin{csharp}
475day = day++ - 5;                                        $\C{// unsafe}$
476day = day & day;
477\end{csharp}
478
479An enumeration can be used in the @if@ and @switch@ statements.
480\begin{cquote}
481\setlength{\tabcolsep}{15pt}
482\begin{tabular}{@{}ll@{}}
483\begin{csharp}
484if ( @day@ <= Week.Fri )
485        Console.WriteLine( "weekday" );
486
487
488
489
490
491\end{csharp}
492&
493\begin{csharp}
494switch ( @day@ ) {
495  case Week.Mon: case Week.Tue: case Week.Wed:
496  case Week.Thu: case Week.Fri:
497        Console.WriteLine( "weekday" ); break;
498  case Week.Sat: case Week.Sun:
499        Console.WriteLine( "weekend" ); break;
500}
501\end{csharp}
502\end{tabular}
503\end{cquote}
504However, there is no mechanism to iterate through an enumeration without an unsafe cast to increment and positions versus values is not handled.
505\begin{csharp}
506for ( Week d = Mon; d <= Sun; @d += 1@ ) {
507        Console.Write( d + " " );
508}
509Mon Tue Wed @3 4 5 6 7 8 9@ Thu Fri Sat Sun
510\end{csharp}
511The @Enum.GetValues@ pseudo-method retrieves an array of the enumeration constants for looping over an enumeration type or variable (expensive operation).
512\begin{csharp}
513foreach ( Week d in @Enum.GetValues@( typeof(Week) ) ) {
514        Console.WriteLine( d + " " + (int)d + " " ); // label, position
515}
516Mon 0, Tue 1, Wed 2, Thu 10, Fri 11, Sat 12, Sun 13,
517\end{csharp}
518Hence, enumerating is not supplied directly by the enumeration, but indirectly through another enumerable type, array.
519
520An enumeration type cannot declare an array dimension but an enumerator can be used as a subscript.
521There is no mechanism to subtype or inherit from an enumeration.
522
523The @Flags@ attribute creates a bit-flags enumeration, making bitwise operators @&@, @|@, @~@ (complement), @^@ (xor) sensible.
524\begin{csharp}
525@[Flags]@ public enum Week {
526        None = 0x0, Mon = 0x1, Tue = 0x2, Wed = 0x4,
527        Thu = 0x8, Fri = 0x10, Sat = 0x20, Sun = 0x40,
528        Weekdays = @Mon | Tue | Wed | Thu | Fri@ $\C{// Weekdays == 0x1f}$
529        Weekend = @Sat | Sun@,                  $\C{// Weekend == 0x60}$
530}
531Week meetings = @Week.Mon | Week.Wed@; $\C{// 0x5}$
532\end{csharp}
533
534
535\section{Golang}
536\label{s:Golang}
537
538Golang has a no enumeration.
539It has @const@ aliasing declarations, similar to \CC \see{\VRef{s:C++RelatedWork}}, for basic types with type inferencing and static initialization (constant expression).
540\begin{Go}
541const R @int@ = 0;  const G @uint@ = 1;  const B = 2; $\C{// explicit typing and type inferencing}$
542const Fred = "Fred";  const Mary = "Mary";  const Jane = "Jane";
543const S = 0;  const T = 0;
544const USA = "USA";  const U = "USA";
545const V = 3.1;  const W = 3.1;
546\end{Go}
547Since these declarations are unmutable variables, they are unscoped and Golang has no overloading.
548
549Golang provides an enumeration-like feature to group together @const@ declaration into a block and introduces a form of auto-initialization.
550\begin{Go}
551const ( R = 0; G; B )                                   $\C{// implicit initialization: 0 0 0}$
552const ( Fred = "Fred"; Mary = "Mary"; Jane = "Jane" ) $\C{// explicit initialization: Fred Mary Jane}$
553const ( S = 0; T; USA = "USA"; U; V = 3.1; W ) $\C{// type change, implicit/explicit: 0 0 USA USA 3.1 3.1}$
554\end{Go}
555The first identifier \emph{must} be explicitly initialized;
556subsequent identifiers can be implicitly or explicitly initialized.
557Implicit initialization is the \emph{previous} (predecessor) identifier value.
558
559Each @const@ declaration provides an implicit integer counter starting at zero, called \lstinline[language=Go]{iota}.
560Using \lstinline[language=Go]{iota} outside of a @const@ block always sets the identifier to zero.
561\begin{Go}
562const R = iota;                                                 $\C{// 0}$
563\end{Go}
564Inside 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.
565\begin{Go}
566const ( R = @iota@; G; B )                              $\C{// implicit: 0 1 2}$
567const ( C = @iota + B + 1@; G; Y )              $\C{// implicit: 3 4 5}$
568\end{Go}
569An underscore \lstinline[language=golang]{const} identifier advances \lstinline[language=Go]{iota}.
570\begin{Go}
571const ( O1 = iota + 1; @_@; O3; @_@; O5 ) // 1, 3, 5 
572\end{Go}
573Auto-initialization reverts from \lstinline[language=Go]{iota} to the previous value after an explicit initialization, but auto-incrementing of \lstinline[language=Go]{iota} continues.
574\begin{Go}
575const ( Mon = iota; Tue; Wed; // 0, 1, 2
576                @Thu = 10@; Fri; Sat; Sun = itoa ) // 10, 10, 10, 6
577\end{Go}
578Auto-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}.
579\begin{Go}
580const ( V1 = iota; V2; @V3 = 7;@ V4 = @iota@ + 1; V5 ) // 0 1 7 4 5
581const ( Mon = iota; Tue; Wed; // 0, 1, 2
582                @Thu = 10;@ Fri = @iota - Wed + Thu - 1@; Sat; Sun ) // 10, 11, 12, 13
583\end{Go}
584Here, @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}.
585Note, because \lstinline[language=Go]{iota} is incremented for an explicitly initialized identifier or @_@,
586at @Fri@ \lstinline[language=Go]{iota} is 4 requiring the minus one to compute the value for @Fri@.
587
588Basic switch and looping are possible.
589\begin{cquote}
590\setlength{\tabcolsep}{20pt}
591\begin{tabular}{@{}ll@{}}
592\begin{Go}
593day := Mon;     // := $\(\Rightarrow\)$ type inferencing
594switch @day@ {
595  case Mon, Tue, Wed, Thu, Fri:
596        fmt.Println( "weekday" );
597  case Sat, Sun:
598        fmt.Println( "weekend" );
599}
600\end{Go}
601&
602\begin{Go}
603
604for i := @Mon@; i <= @Sun@; i += 1 {
605        fmt.Println( i )
606}
607
608
609
610\end{Go}
611\end{tabular}
612\end{cquote}
613However, the loop prints the values from 0 to 13 because there is no actual enumeration.
614
615A constant variable can be used as an array dimension or a subscript.
616\begin{Go}
617var ar[@Sun@] int
618ar[@Mon@] = 3
619\end{Go}
620
621
622\section{Java}
623
624Java provides an enumeration using a specialized class.
625A basic Java enumeration is an opaque enumeration, where the enumerators are constants.
626\begin{Java}
627enum Week {
628        Mon, Tue, Wed, Thu, Fri, Sat, Sun;
629}
630Week day = Week.Sat;
631\end{Java}
632The enumerators members are scoped and cannot be made \lstinline[language=java]{public}, hence require qualification.
633The value of an enumeration instance is restricted to its enumerators.
634
635The position (ordinal) and label are accessible but there is no value.
636\begin{Java}
637System.out.println( day.!ordinal()! + " " + !day! + " " + day.!name()! );
6385 Sat Sat
639\end{Java}
640Since @day@ has no value, it prints its label (name).
641The member @valueOf@ is the inverse of @name@ converting a string to enumerator.
642\begin{Java}
643day = Week.valueOf( "Wed" );
644\end{Java}
645Extra members can be added to provide specialized operations.
646\begin{Java}
647public boolean isWeekday() { return !ordinal()! <= Fri.ordinal(); }
648public boolean isWeekend() { return Sat.ordinal() <= !ordinal()!; }
649\end{Java}
650Notice the unqualified calls to @ordinal@ in the members implying a \lstinline[language=Java]{this} to some implicit implementation variable, likely an @int@.
651
652Enumerator values require an enumeration type (any Java type may be used) and implementation member.
653\begin{Java}
654enum Week {
655        Mon!(1)!, Tue!(2)!, Wed!(3)!, Thu!(4)!, Fri!(5)!, Sat!(6)!, Sun!(7)!; // must appear first
656        private !long! day;                                     $\C{// enumeration type and implementation member}$
657        private Week( !long! d ) { day = d; } $\C{// enumerator initialization}$
658};
659Week day = Week.Sat;
660\end{Java}
661The position, value, and label are accessible.
662\begin{Java}
663System.out.println( !day.ordinal()! + " " + !day.day! + " " + !day.name()! );
6645 6 Sat
665\end{Java}
666If 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@.
667The implementation constructor must be private since it is only used internally to initialize the enumerators.
668Initialization occurs at the enumeration-type declaration for each enumerator in the first line.
669
670Enumerations can be used in the @if@ and @switch@ statements but only for equality tests.
671\begin{cquote}
672\setlength{\tabcolsep}{15pt}
673\begin{tabular}{@{}ll@{}}
674\begin{Java}
675if ( !day! == Week.Fri )
676        System.out.println( "Fri" );
677
678
679
680
681\end{Java}
682&
683\begin{Java}
684switch ( !day! ) {
685  case Mon: case Tue: case Wed: case Thu: case Fri:
686        System.out.println( "weekday" );  break;
687  case Sat: case Sun:
688        System.out.println( "weekend" );  break;
689}
690\end{Java}
691\end{tabular}
692\end{cquote}
693Notice enumerators in the @switch@ statement do not require qualification.
694
695There 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}.
696Like \Csharp, looping over an enumeration is done using method @values@, which returns an array of enumerator values (expensive operation).
697\begin{Java}
698for ( Week d : Week.values() ) {
699        System.out.print( d.ordinal() + d.day + " " +  d.name() + ",  " );
700}
7010 1 Mon,  1 2 Tue,  2 3 Wed,  3 4 Thu,  4 5 Fri,  5 6 Sat,  6 7 Sun, 
702\end{Java}
703Like \Csharp, enumerating is supplied indirectly through another enumerable type, not via the enumeration.
704
705An enumeration type cannot declare an array dimension nor can an enumerator be used as a subscript.
706Enumeration inheritence is disallowed because an enumeration is \lstinline[language=Java]{final}.
707
708Java 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.
709There is also a specialized version of @HashMap@ with enumerator keys, which has performance benefits.
710
711
712\section{Rust}
713
714% https://doc.rust-lang.org/reference/items/enumerations.html
715
716Rust @enum@ provides two largely independent mechanisms from a single language feature: an ADT and an enumeration.
717When @enum@ is an ADT, pattern matching is used to discriminate among the variant types.
718\begin{cquote}
719\begin{tabular}{@{}l@{\hspace{30pt}}ll@{}}
720\begin{rust}
721struct S {
722        i : isize,  j : isize
723}
724let mut s = S{ i : 3, j : 4 };
725enum @ADT@ {
726        I( isize ), $\C[1in]{// int}$
727        F( f64 ),   $\C{// float}$
728        S( S ),     $\C{// struct}\CRT$
729}
730\end{rust}
731&
732\begin{rust}
733let mut adt : ADT;
734adt = ADT::I(3);  println!( "{:?}", adt );
735adt = ADT::F(3.5);  println!( "{:?}", adt );
736adt = ADT::S(s);  println!( "{:?}", adt );
737@match@ adt {
738        ADT::I( i ) => println!( "{:}", i ),
739        ADT::F( f ) => println!( "{:}", f ),
740        ADT::S( s ) => println!( "{:} {:}", s.i, s.j ),
741}
742\end{rust}
743&
744\begin{rust}
745I(3)
746F(3.5)
747S(S { i: 3, j: 4 })
7483 4
749
750
751
752
753
754\end{rust}
755\end{tabular}
756\end{cquote}
757Even when the variant types are the unit type, the ADT is still not an enumeration because there is no enumerating \see{\VRef{s:AlgebraicDataType}}.
758\begin{rust}
759enum Week { Mon, Tues, Wed, Thu, Fri, Sat, Sun@,@ } // terminating comma
760let mut week : Week = Week::Mon;
761match week {
762        Week::Mon => println!( "Mon" ),
763        ...
764        Week::Sun => println!( "Sun" ),
765}
766\end{rust}
767
768However, Rust allows direct setting of the ADT constructor, which means it is actually a tag.
769\begin{cquote}
770\setlength{\tabcolsep}{15pt}
771\begin{tabular}{@{}ll@{}}
772\begin{rust}
773enum Week {
774        Mon, Tues, Wed, // start 0
775        Thu @= 10@, Fri,
776        Sat, Sun,
777}
778
779\end{rust}
780&
781\begin{rust}
782#[repr(u8)]
783enum ADT {
784        I(isize) @= 5@,  // ???
785        F(f64) @= 10@,
786        S(S) @= 0@,
787}
788\end{rust}
789\end{tabular}
790\end{cquote}
791Through 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}.
792When tags represent non-unit types, Rust largely precludes accessing the tag because the semantics become meaningless.
793Hence, the two mechanisms are largely disjoint, and ony the enumeration component is discussed.
794
795In detail, the @enum@ type has an implicit integer tag (discriminant), with a unique value for each variant type.
796Direct initialization is by a compile-time expression generating a constant value.
797Indirect initialization (without initialization, @Fri@/@Sun@) is auto-initialized: from left to right, starting at zero or the next explicitly initialized constant, incrementing by @1@.
798There is an explicit cast from the tag to integer.
799\begin{rust}
800let mut mon : isize = Week::Mon as isize;
801\end{rust}
802An enumeration can be used in the @if@ and \lstinline[language=rust]{match} (@switch@) statements.
803\begin{cquote}
804\setlength{\tabcolsep}{8pt}
805\begin{tabular}{@{}ll@{}}
806\begin{c++}
807if @week as isize@ == Week::Mon as isize {
808        println!( "{:?}", week );
809}
810
811
812\end{c++}
813&
814\begin{c++}
815match @week@ {
816        Week::Mon | Week:: Tue | Week::Wed | Week::Thu
817                | Week::Fri => println!( "weekday" ),
818        Week::Sat | Week:: Sun => println!( "weekend" ),
819}
820\end{c++}
821\end{tabular}
822\end{cquote}
823However, there is no mechanism to iterate through an enumeration without casting to integral and positions versus values is not handled.
824\begin{c++}
825for d in Week::Mon as isize ..= Week::Sun as isize {
826        print!( "{:?} ", d );
827}
8280 1 2 @3 4 5 6 7 8 9@ 10 11 12 13
829\end{c++}
830An enumeration type cannot declare an array dimension nor as a subscript.
831There is no mechanism to subtype or inherit from an enumeration.
832
833
834\section{Swift}
835
836% https://www.programiz.com/swift/online-compiler
837
838Like Rust, Swift @enum@ provides two largely independent mechanisms from a single language feature: an ADT and an enumeration.
839When @enum@ is an ADT, pattern matching is used to discriminate among the variant types.
840\begin{cquote}
841\setlength{\tabcolsep}{20pt}
842\begin{tabular}{@{}l@{\hspace{55pt}}ll@{}}
843\begin{swift}
844struct S {
845        var i : Int,  j : Int
846}
847var s = S( i : 3, j : 5 )
848@enum@ ADT {
849        case I(Int)   $\C[1.125in]{// int}$
850        case F(Float) $\C{// float}$
851        case S(S)     $\C{// struct}\CRT$
852}
853\end{swift}
854&
855\begin{swift}
856var adt : ADT
857adt = .I( 3 );  print( adt )
858adt = .F( 3.5 );  print( adt )
859adt = .S( s );  print( adt )
860@switch@ adt {  // pattern matching
861        case .I(let i):  print( i )
862        case .F(let f):  print( f )
863        case .S(let s):  print( s.i, s.j )
864}
865\end{swift}
866&
867\begin{swift}
868I(3)
869F(3.5)
870S(S(i: 3, j: 5))
8713 5
872
873
874
875
876
877\end{swift}
878\end{tabular}
879\end{cquote}
880(Note, after an @adt@'s type is know, the enumerator is inferred without qualification, \eg @.I(3)@.)
881
882An enumeration is created when \emph{all} the enumerators are unit-type, which is like a scoped, opaque enumeration.
883\begin{swift}
884enum Week {
885        case Mon, Tue, Wed, Thu, Fri, Sat, Sun // unit-type
886};
887var week : Week = @Week.Mon@;
888\end{swift}
889As well, it is possible to type \emph{all} the enumerators with a common type, and set different values for each enumerator;
890for integral types, there is auto-incrementing.
891\begin{cquote}
892\setlength{\tabcolsep}{15pt}
893\begin{tabular}{@{}lll@{}}
894\begin{swift}
895enum WeekInt: @Int@ {
896        case Mon, Tue, Wed, Thu = 10, Fri,
897                        Sat = 4, Sun // auto-incrementing
898};
899\end{swift}
900&
901\begin{swift}
902enum WeekStr: @String@ {
903        case Mon = "MON", Tue, Wed, Thu, Fri,
904                        Sat = "SAT", Sun
905};
906\end{swift}
907\end{tabular}
908\end{cquote}
909An enumeration only supports equality comparison between enumerator values, unless it inherits from @Comparable@, adding relational operators @<@, @<=@, @>@, and @>=@.
910
911An enumeration can have methods.
912\begin{swift}
913enum Week: Comparable {
914        case Mon, Tue, Wed, Thu, Fri, Sat, Sun // unit-type
915        func @isWeekday() -> Bool@ { return self <= .Fri }    // method
916        func @isWeekend() -> Bool@ { return .Sat <= self }  // method
917};
918\end{swift}
919An enumeration can be used in the @if@ and @switch@ statements, where @switch@ must be exhaustive or have a @default@.
920\begin{cquote}
921\setlength{\tabcolsep}{15pt}
922\begin{tabular}{@{}ll@{}}
923\begin{swift}
924if @week <= .Fri@ {
925        print( "weekday" );
926}
927
928
929\end{swift}
930&
931\begin{swift}
932switch @week@ {
933        case .Mon: print( "Mon" )
934        ...
935        case .Sun: print( "Sun" )
936}
937\end{swift}
938\end{tabular}
939\end{cquote}
940
941Enumerating is accomplished by inheriting from @CaseIterable@ without any associated values.
942\begin{swift}
943enum Week: Comparable, @CaseIterable@ {
944        case Mon, Tue, Wed, Thu, Fri, Sat, Sun // unit-type
945};
946var weeki : Week = Week.Mon;
947if weeki <= .Fri {
948        print( "weekday" );
949}
950for day in Week@.allCases@ {
951        print( day, terminator:" " ) 
952}
953weekday
954Mon Tue Wed Thu Fri Sat Sun
955\end{swift}
956The @enum.allCases@ property returns a collection of all the cases for looping over an enumeration type or variable (expensive operation).
957
958A typed enumeration is accomplished by inheriting from any Swift type, and accessing the underlying enumerator value is done with attribute @rawValue@.
959Type @Int@ has auto-incrementing from previous enumerator;
960type @String@ has auto-incrementing of the enumerator label.
961\begin{cquote}
962\setlength{\tabcolsep}{15pt}
963\begin{tabular}{@{}lll@{}}
964\begin{swift}
965enum WeekInt: @Int@, CaseIterable {
966        case Mon, Tue, Wed, Thu = 10, Fri,
967                        Sat = 4, Sun // auto-incrementing
968};
969for day in WeekInt.allCases {
970        print( day@.rawValue@, terminator:" " ) 
971}
9720 1 2 10 11 4 5 
973\end{swift}
974&
975\begin{swift}
976enum WeekStr: @String@, CaseIterable {
977        case Mon = "MON", Tue, Wed, Thu, Fri,
978                        Sat = "SAT", Sun
979};
980for day in WeekStr.allCases {
981        print( day@.rawValue@, terminator:" " ) 
982}
983MON Tue Wed Thu Fri SAT Sun
984\end{swift}
985\end{tabular}
986\end{cquote}
987
988There is a bidirectional conversion from typed enumerator to @rawValue@ and vise versa.
989\begin{swift}
990var weekInt : WeekInt = WeekInt.Mon;
991if let opt = WeekInt( rawValue: 0 ) {  // test optional return value
992        print( weekInt.rawValue, opt )  // 0 Mon
993} else {
994        print( "invalid weekday lookup" )
995}
996\end{swift}
997Conversion from @rawValue@ to enumerator may fail (bad lookup), so the result is an optional value.
998
999
1000\section{Python 3.13}
1001% https://docs.python.org/3/howto/enum.html
1002
1003Python is a dynamically-typed reflexive programming language with multiple incompatible versions.
1004The generality of the language makes it is possible to extend existing or build new language features.
1005As 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.
1006Therefore, the following discussion is (mostly) restricted to the core enumeration features in Python 3.13.
1007
1008A Python enumeration is not a basic type;
1009it is a @class@ inheriting from the @Enum@ class.
1010The @Enum@ class presents a set of scoped enumerators, where each enumerator is a pair object with a \emph{constant} string name and arbitrary value.
1011Hence, an enumeration instance is a fixed type (enumeration pair), and its value is the type of one of the enumerator pairs.
1012
1013The enumerator value fields must be explicitly initialized and be \emph{unique}.
1014\begin{python}
1015class Week(!Enum!): Mon = 1; Tue = 2; Wed = 3; Thu = 4; Fri = 5; Sat = 6; Sun = 7
1016\end{python}
1017and/or explicitly auto initialized, \eg:
1018\begin{python}
1019class Week(Enum): Mon = 1; Tue = 2; Wed = 3; Thu = 10; Fri = !auto()!; Sat = 4; Sun = !auto()!
1020Mon : 1 Tue : 2 Wed : 3 Thu : 10 Fri : !11! Sat : 4 Sun : !12!
1021\end{python}
1022where @auto@ increments by 1 from the previous @auto@ value \see{Golang \lstinline[language=Go]{iota}, \VRef{s:Golang}}.
1023@auto@ is controlled by member @_generate_next_value_()@, which can be overridden:
1024\begin{python}
1025@staticmethod
1026def _generate_next_value_( name, start, count, last_values ):
1027        return name
1028\end{python}
1029
1030There is no direct concept of restricting the enumerators in an enumeration \emph{instance} because the dynamic typing changes the type.
1031\begin{python}
1032class RGB(Enum): Red = 1; Green = 2; Blue = 3
1033day : Week = Week.Tue;          $\C{\# type is Week}$
1034!day = RGB.Red!                         $\C{\# type is RGB}$
1035!day : Week = RGB.Red!          $\C{\# type is RGB}$
1036\end{python}
1037The enumerators are constants and cannot be reassigned.
1038Hence, while enumerators can be different types,
1039\begin{python}
1040class Diff(Enum): Int = 1; Float = 3.5; Str = "ABC"
1041\end{python}
1042it is not an ADT because the enumerator names are not constructors.
1043
1044An enumerator initialized with the same value is an alias and invisible at the enumeration level, \ie the alias is substituted for its aliasee.
1045\begin{python}
1046class WeekD(Enum): Mon = 1; Tue = 2; Wed = 3; Thu = !10!; Fri = !10!; Sat = !10!; Sun = !10!
1047\end{python}
1048Here, the enumeration has only 4 enumerators and 3 aliases.
1049An alias is only visible by dropping down to the @class@ level and asking for class members.
1050Aliasing is prevented using the @unique@ decorator.
1051\begin{python}
1052!@unique!
1053class DupVal(Enum): One = 1; Two = 2; Three = !3!; Four = !3!
1054ValueError: duplicate values found in <enum 'DupVal'>: Four -> Three
1055\end{python}
1056
1057\begin{lrbox}{\myboxA}
1058\begin{python}
1059def by_position(enum_type, position):
1060        for index, value in enumerate(enum_type):
1061                if position == index: return value
1062        raise Exception("by_position out of range")
1063\end{python}
1064\end{lrbox}
1065There are bidirectional enumeration pseudo-functions for label and value, but there is no concept of access using ordering (position).\footnote{
1066There is an $O(N)$ mechanism to access an enumerator's value by position. \newline \usebox\myboxA}
1067\begin{cquote}
1068\setlength{\tabcolsep}{15pt}
1069\begin{tabular}{@{}ll@{}}
1070\begin{python}
1071Week.Thu.value == 4;
1072Week.Thu.name == "Thu";
1073\end{python}
1074&
1075\begin{python}
1076Week( 4 ) == Week.Thu
1077Week["Thu"].value == 4
1078\end{python}
1079\end{tabular}
1080\end{cquote}
1081@Enum@ only supports equality comparison between enumerator values.
1082There are multiple library extensions to @Enum@, \eg @OrderedEnum@ recipe class, adding relational operators @<@, @<=@, @>@, and @>=@.
1083
1084An enumeration \lstinline[language=python]{class} can have methods.
1085\begin{python}
1086class Week(!OrderedEnum!):
1087        Mon = 1; Tue = 2; Wed = 3; Thu = 4; Fri = 5; Sat = 6; Sun = 7
1088        def !isWeekday(self)!:          # method
1089                return Week(self.value) !<=! Week.Fri
1090        def !isWeekend(self)!:          # method
1091                return Week.Sat !<=! Week(self.value) 
1092\end{python}
1093
1094An enumeration can be used in the @if@ and @switch@ statements but only for equality tests, unless extended to @OrderedEnum@.
1095\begin{cquote}
1096\setlength{\tabcolsep}{12pt}
1097\begin{tabular}{@{}ll@{}}
1098\begin{python}
1099if day <= Week.Fri :
1100        print( "weekday" );
1101
1102
1103
1104\end{python}
1105&
1106\begin{python}
1107match day:
1108        case Week.Mon | Week.Tue | Week.Wed | Week.Thu | Week.Fri:
1109                print( "weekday" );
1110        case Week.Sat | Week.Sun:
1111                print( "weekend" );
1112\end{python}
1113\end{tabular}
1114\end{cquote}
1115Looping is performed using the enumeration type or @islice@ from @itertools@ based on position.
1116\begin{python}
1117for day in !Week!:                                      $\C[2.25in]{\# Mon : 1 Tue : 2 Wed : 3 Thu : 4 Fri : 5 Sat : 6 Sun : 7}$
1118        print( day.name, ":", day.value, end=" " )
1119for day in !islice(Week, 0, 5)!:        $\C{\# Mon : 1 Tue : 2 Wed : 3 Thu : 4 Fri : 5}$
1120        print( day.name, ":", day.value, end=" " )
1121for day in !islice(Week, 5, 7)!:        $\C{\# Sat : 6 Sun : 7}$
1122        print( day.name, ":", day.value, end=" " )
1123for day in !islice(Week,0, 7, 2)!:      $\C{\# Mon : 1 Wed : 3 Fri : 5 Sun : 7}\CRT$
1124        print( day.name, ":", day.value, end=" " )
1125\end{python}
1126Iterating that includes alias names only (strings) is done using attribute @__members__@.
1127\begin{python}
1128for day in WeekD.__members__:
1129        print( day, ":", end=" " )
1130Mon : Tue : Wed : Thu : Fri : Sat : Sun
1131\end{python}
1132
1133Enumeration subclassing is allowed only if the enumeration base-class does not define any members.
1134\begin{python}
1135class WeekE(OrderedEnum): !pass!;  # no members
1136class WeekDay(WeekE): Mon = 1; Tue = 2; Wed = 3; Thu = 4; Fri = 5;
1137class WeekEnd(WeekE): Sat = 6; Sun = 7
1138\end{python}
1139Here, type @WeekE@ is an abstract type because the dynamic typing never uses it.
1140\begin{cquote}
1141\setlength{\tabcolsep}{25pt}
1142\begin{tabular}{@{}ll@{}}
1143\begin{python}
1144print( type(WeekE) )
1145day : WeekE = WeekDay.Fri       # set type
1146print( type(day), day )
1147day = WeekEnd.Sat                           # set type
1148print( type(day), day )
1149\end{python}
1150&
1151\begin{python}
1152<$class$ 'enum.EnumType'>
1153
1154<enum 'WeekDay'> WeekDay.Fri
1155
1156<enum 'WeekEnd'> WeekEnd.Sat
1157\end{python}
1158\end{tabular}
1159\end{cquote}
1160
1161There are a number of supplied enumeration base-types: @IntEnum@, @StrEnum@, @IntFalg@, @Flag@, which restrict the values in an enum using multi-inheritance.
1162@IntEnum@ is a subclass of @int@ and @Enum@, allowing enumerator comparison to @int@ and other enumerators of this type (like C enumerators).
1163@StrEnum@ is the same as @IntEnum@ but a subclass of the string type \lstinline[language=python]{str}.
1164@IntFlag@, is a restricted subclass of @int@ where the enumerators can be combined using the bitwise operators (@&@, @|@, @^@, @~@) and the result is an @IntFlag@ member.
1165@Flag@ is the same as @IntFlag@ but cannot be combined with, nor compared against, any other @Flag@ enumeration, nor @int@.
1166Auto increment for @IntFlag@ and @Flag@ is by powers of 2.
1167Enumerators that are a combinations of single bit enumerators are aliases, and hence, invisible.
1168The following is an example for @Flag@.
1169\begin{python}
1170class WeekF(Flag): Mon = 1; Tue = 2; Wed = 4; Thu = !auto()!; Fri = 16; Sat = 32; Sun = 64; \
1171          Weekday = Mon | Tue | Wed | Thu | Fri; \
1172          Weekend = Sat | Sun
1173print( f"0x{repr(WeekF.Weekday.value)} 0x{repr(WeekF.Weekend.value)}" )
11740x31 0x96
1175\end{python}
1176It is possible to enumerate through a @Flag@ enumerator (no aliases):
1177\begin{python}
1178for day in WeekF:
1179        print( f"{day.name}: {day.value}", end=" ")
1180Mon: 1 Tue: 2 Wed: 4 Thu: 8 Fri: 16 Sat: 32 Sun: 64 
1181\end{python}
1182and a combined alias enumerator for @Flag@.
1183\begin{cquote}
1184\setlength{\tabcolsep}{15pt}
1185\begin{tabular}{@{}ll@{}}
1186\begin{python}
1187weekday = WeekF.Weekday
1188for day in weekday:
1189        print( f"{day.name}:"
1190                   f" {day.value}", end=" " )
1191Mon: 1 Tue: 2 Wed: 4 Thu: 8 Fri: 16 
1192\end{python}
1193&
1194\begin{python}
1195weekend = WeekF.Weekend
1196for day in weekend:
1197        print( f"{day.name}:"
1198                   f" {day.value}", end=" " )
1199Sat: 32 Sun: 64 
1200\end{python}
1201\end{tabular}
1202\end{cquote}
1203
1204
1205\section{OCaml}
1206
1207% https://ocaml.org/docs/basic-data-types#enumerated-data-types
1208% https://dev.realworldocaml.org/runtime-memory-layout.html
1209
1210Like Haskell, OCaml @enum@ provides two largely independent mechanisms from a single language feature: an ADT and an enumeration.
1211When @enum@ is an ADT, pattern matching is used to discriminate among the variant types.
1212\begin{cquote}
1213\setlength{\tabcolsep}{20pt}
1214\begin{tabular}{@{}l@{\hspace{35pt}}ll@{}}
1215\begin{ocaml}
1216type s = { i : int; j : int }
1217let sv : s = { i = 3; j = 5 }
1218@type@ adt =
1219        I of int |    $\C[1in]{// int}$
1220        F of float |  $\C{// float}$
1221        S of s        $\C{// struct}\CRT$
1222
1223
1224\end{ocaml}
1225&
1226\begin{ocaml}
1227let adtprt( adtv : adt ) =
1228        @match@ adtv with (* pattern matching *)
1229                I i -> printf "%d\n" i |
1230                F f -> printf "%g\n" f |
1231                S sv -> printf "%d %d\n" sv.i sv.j
1232let adtv : adt = I(3)       let _ = adtprt( adtv )
1233let adtv : adt = F(3.5)   let _ = adtprt( adtv )
1234let adtv : adt = S(sv)    let _ = adtprt( adtv )
1235\end{ocaml}
1236&
1237\begin{ocaml}
12383
12393.5
12403 5
1241
1242
1243
1244
1245
1246\end{ocaml}
1247\end{tabular}
1248\end{cquote}
1249(Note, after an @adtv@'s type is know, the enumerator is inferred without qualification, \eg @I(3)@.)
1250The type names are independent from the type value, and mapped to an opaque, ascending, integral tag, starting from 0, supporting relational operators @<@, @<=@, @>@, and @>=@.
1251\begin{cquote}
1252\setlength{\tabcolsep}{10pt}
1253\begin{tabular}{@{}l@{\hspace{25pt}}ll@{}}
1254\begin{ocaml}
1255let silly( adtv : adt ) =
1256        if adtv <= F(3.5) then
1257                printf "<= F\n"
1258        else if adtv >= S(sv) then
1259                printf ">= S\n"
1260\end{ocaml}
1261&
1262\begin{ocaml}
1263let adtv : adt = I(3)       let _ = silly( adtv )
1264let adtv : adt = F(3.5)   let _ = silly( adtv )
1265let adtv : adt = S(sv)    let _ = silly( adtv )
1266
1267
1268\end{ocaml}
1269&
1270\begin{ocaml}
1271<= F
1272<= F
1273>= S
1274
1275
1276\end{ocaml}
1277\end{tabular}
1278\end{cquote}
1279In the example, type values must be specified (any appropriate values work) but ignored in the relational comparison of the type tag.
1280
1281An 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.
1282\begin{ocaml}
1283type week = Mon | Tue | Wed | Thu | Fri | Sat | Sun
1284let day : week = Mon
1285\end{ocaml}
1286Since the type names are opaque, a type-tag value cannot be explicitly set nor can it have a type other than integral.
1287
1288As 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.
1289
1290Enumerating is accomplished by deriving from @enumerate@.
1291
1292Enumeration subtyping is allowed but inheritance is restricted to classes not types.
1293\begin{ocaml}
1294type weekday = Mon | Tue | Wed | Thu | Fri
1295type weekend = Sat | Sun
1296type week = Weekday of weekday | Weekend of weekend
1297let day : week = Weekend Sun
1298\end{ocaml}
1299
1300%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1301
1302\begin{comment}
1303Date: Wed, 13 Mar 2024 10:52:34 -0400
1304Subject: Re: OCaml
1305To: "Peter A. Buhr" <pabuhr@uwaterloo.ca>
1306From: Gregor Richards <gregor.richards@uwaterloo.ca>
1307
1308On 3/12/24 18:34, Peter A. Buhr wrote:
1309> Gregor, attached is a section Jiada wrote on OCaml (1-page).
1310> Does it reflect our discussion about functional languages and enumerations?
1311
1312Yeah, I think so. The most important part, i.e., that once they're
1313parameterized they're not really enumerations at all, is covered clearly
1314enough.
1315
1316A couple quibbles:
1317
1318<<a list of untyped tags>>
1319
1320This is true, but leaking implementation details. These are nullary datatype
1321constructors. Indeed, you later talk about "tagged variants", which are really
1322just parameterized variants, using the term "tag" differently, confusing the
1323term "tag" further.
1324
1325<<Because week is a summation of values Mon to Sun, it is a sum type in
1326turns of the functional-programming paradigm>>
1327
1328It is a *union* of values and is a *union* type.
1329
1330With valediction,
1331  - Gregor Richards
1332
1333
1334Date: Thu, 14 Mar 2024 21:45:52 -0400
1335Subject: Re: OCaml "enums" do come with ordering
1336To: "Peter A. Buhr" <pabuhr@uwaterloo.ca>
1337From: Gregor Richards <gregor.richards@uwaterloo.ca>
1338
1339On 3/14/24 21:30, Peter A. Buhr wrote:
1340> I've marked 3 places with your name to shows places with enum ordering.
1341>
1342> open Printf
1343> type week = Mon | Tue | Wed | Thu | Fri | Sat | Sun
1344> let day : week = Mon
1345> let take_class( d : week ) =
1346>       if d <= Fri then                                (* Gregor *)
1347>               printf "week\n"
1348>       else if d >= Sat then                   (* Gregor *)
1349>               printf "weekend\n";
1350>       match d with
1351>               Mon | Wed -> printf "CS442\n" |
1352>               Tue | Thu -> printf "CS343\n" |
1353>               Fri -> printf "Tutorial\n" |
1354>               _ -> printf "Take a break\n"
1355>
1356> let _ = take_class( Mon ); take_class( Sat );
1357>
1358> type colour = Red | Green of string | Blue of int * float
1359> let c = Red
1360> let _ = match c with Red -> printf "Red, "
1361> let c = Green( "abc" )
1362> let _ = match c with Green g -> printf "%s, " g
1363> let c = Blue( 1, 1.5 )
1364> let _ = match c with Blue( i, f ) -> printf "%d %g\n" i f
1365>
1366> let check_colour(c: colour): string =
1367>       if c < Green( "xyz" ) then              (* Gregor *)
1368>               printf "green\n";
1369>       match c with
1370>               Red -> "Red" |
1371>               Green g -> g |
1372>               Blue(i, f) -> string_of_int i ^ string_of_float f
1373> let _ = check_colour( Red ); check_colour( Green( "xyz" ) );
1374>
1375> type stringList = Empty | Pair of string * stringList
1376> let rec len_of_string_list(l: stringList): int =
1377>       match l with
1378>               Empty -> 0 |
1379>               Pair(_ , r) -> 1 + len_of_string_list r
1380>
1381> let _ = for i = 1 to 10 do
1382>       printf "%d, " i
1383> done
1384>
1385> (* Local Variables: *)
1386> (* tab-width: 4 *)
1387> (* compile-command: "ocaml test.ml" *)
1388> (* End: *)
1389
1390My functional-language familiarity is far more with Haskell than OCaml.  I
1391mostly view OCaml through a lens of "it's Haskell but with cheating".  Haskell
1392"enums" (ADTs) aren't ordered unless you specifically and manually put them in
1393the Ord typeclass by defining the comparators.  Apparently, OCaml has some
1394other rule, which I would guess is something like "sort by tag then by order of
1395parameter". Having a default behavior for comparators is *bizarre*; my guess
1396would be that it gained this behavior in its flirtation with object
1397orientation, but that's just a guess (and irrelevant).
1398
1399This gives a total order, but not enumerability (which would still be
1400effectively impossible or even meaningless since enums are just a special case
1401of ADTs).
1402
1403With valediction,
1404  - Gregor Richards
1405
1406Date: Wed, 20 Mar 2024 18:16:44 -0400
1407Subject: Re:
1408To: "Peter A. Buhr" <pabuhr@uwaterloo.ca>
1409From: Gregor Richards <gregor.richards@uwaterloo.ca>
1410
1411
1412On 3/20/24 17:26, Peter A. Buhr wrote:
1413> Gregor, everyone at this end would like a definition of "enumerability". Can
1414> you formulate one?
1415
1416According to the OED (emphasis added to the meaning I'm after):
1417
1418enumerate (verb, transitive). To count, ascertain the number of; **more
1419usually, to mention (a number of things or persons) separately, as if for the
1420purpose of counting**; to specify as in a list or catalogue.
1421
1422With C enums, if you know the lowest and highest value, you can simply loop
1423over them in a for loop (this is, of course, why so many enums come with an
1424ENUM_WHATEVER_LAST value). But, I would be hesitant to use the word "loop" to
1425describe enumerability, since in functional languages, you would recurse for
1426such a purpose.
1427
1428In Haskell, in order to do something with every member of an "enumeration", you
1429would have to explicitly list them all. The type system will help a bit since
1430it knows if you haven't listed them all, but you would have to statically have
1431every element in the enumeration.  If somebody added new elements to the
1432enumeration later, your code to enumerate over them would no longer work
1433correctly, because you can't simply say "for each member of this enumeration do
1434X". In Haskell that's because there aren't actually enumerations; what they use
1435as enumerations are a degenerate form of algebraic datatypes, and ADTs are
1436certainly not enumerable. In OCaml, you've demonstrated that they impose
1437comparability, but I would still assume that you can't make a loop over every
1438member of an enumeration. (But, who knows!)
1439
1440Since that's literally what "enumerate" means, it seems like a rather important
1441property for enumerations to have ;)
1442
1443With valediction,
1444  - Gregor Richards
1445
1446
1447From: Andrew James Beach <ajbeach@uwaterloo.ca>
1448To: Gregor Richards <gregor.richards@uwaterloo.ca>, Peter Buhr <pabuhr@uwaterloo.ca>
1449CC: Michael Leslie Brooks <mlbrooks@uwaterloo.ca>, Fangren Yu <f37yu@uwaterloo.ca>,
1450        Jiada Liang <j82liang@uwaterloo.ca>
1451Subject: Re: Re:
1452Date: Thu, 21 Mar 2024 14:26:36 +0000
1453
1454Does this mean that not all enum declarations in C create enumerations? If you
1455declare an enumeration like:
1456
1457enum Example {
1458        Label,
1459        Name = 10,
1460        Tag = 3,
1461};
1462
1463I don't think there is any way to enumerate (iterate, loop, recurse) over these
1464values without listing all of them.
1465
1466
1467Date: Thu, 21 Mar 2024 10:31:49 -0400
1468Subject: Re:
1469To: Andrew James Beach <ajbeach@uwaterloo.ca>, Peter Buhr <pabuhr@uwaterloo.ca>
1470CC: Michael Leslie Brooks <mlbrooks@uwaterloo.ca>, Fangren Yu <f37yu@uwaterloo.ca>,
1471    Jiada Liang <j82liang@uwaterloo.ca>
1472From: Gregor Richards <gregor.richards@uwaterloo.ca>
1473
1474I consider this conclusion reasonable. C enums can be nothing more than const
1475ints, and if used in that way, I personally wouldn't consider them as
1476enumerations in any meaningful sense, particularly since the type checker
1477essentially does nothing for you there. Then they're a way of writing consts
1478repeatedly with some textual indicator that these definitions are related; more
1479namespace, less enum.
1480
1481When somebody writes bitfield members as an enum, is that *really* an
1482enumeration, or just a use of the syntax for enums to keep related definitions
1483together?
1484
1485With valediction,
1486  - Gregor Richards
1487
1488
1489Date: Tue, 16 Apr 2024 11:04:51 -0400
1490Subject: Re: C unnamed enumeration
1491To: "Peter A. Buhr" <pabuhr@uwaterloo.ca>
1492CC: <ajbeach@uwaterloo.ca>, <j82liang@uwaterloo.ca>, <mlbrooks@uwaterloo.ca>,
1493        <f37yu@uwaterloo.ca>
1494From: Gregor Richards <gregor.richards@uwaterloo.ca>
1495
1496On 4/16/24 09:55, Peter A. Buhr wrote:
1497> So what is a variant? Is it a set of tag names, which might be a union or is it
1498> a union, which might have tag names?
1499
1500Your tagless variant bears no resemblance to variants in any functional
1501programming language. A variant is a tag AND a union. You might not need to put
1502anything in the union, in which case it's a pointless union, but the named tag
1503is absolutely mandatory. That's the thing that varies.
1504
1505I was unaware of std::variant. As far as functional languages are concerned,
1506std::variant IS NOT A VARIANT. Perhaps it would be best to use the term ADT for
1507the functional language concept, because that term has no other meanings.
1508
1509An ADT cannot not have a named tag. That's meaningless. The tag is the data
1510constructor, which is the thing you actually define when you define an ADT. It
1511is strictly the union that's optional.
1512
1513With valediction,
1514  - Gregor Richards
1515\end{comment}
1516
1517
1518\section{Comparison}
1519
1520\VRef[Table]{t:FeatureLanguageComparison} shows a comparison of enumeration features and programming languages.
1521The features are high level and may not capture nuances within a particular language
1522The @const@ feature is simple macros substitution and not a typed enumeration.
1523
1524\begin{table}
1525\caption{Enumeration Feature / Language Comparison}
1526\label{t:FeatureLanguageComparison}
1527\small
1528\setlength{\tabcolsep}{3pt}
1529\newcommand{\CM}{\checkmark}
1530\begin{tabular}{r|c|c|c|c|c|c|c|c|c|c|c|c|c}
1531                                &Pascal & Ada   &\Csharp& OCaml & Java  &Modula-3&Golang& Rust  & Swift & Python& C             & \CC   & \CFA  \\
1532\hline
1533@const@                 & \CM   &               &               &               &               &               & \CM   &               &               &               &               & \CM   &               \\
1534\hline
1535\hline
1536opaque                  &               &               &               &               &               &               &               &               &               &               &               &               & \CM   \\
1537\hline
1538typed                   &               &               &               &               &               &               &               &               &               &               & @int@ & integral      & @T@   \\
1539\hline
1540safe                    &               &               &               &               &               &               &               &               &               &               &               & \CM   & \CM   \\
1541\hline
1542ordered                 &               &               &               &               &               &               &               &               &               &               & \CM   & \CM   & \CM   \\
1543\hline
1544dup. values             &               &               &               &               &               &               &               &               &               & alias & \CM   & \CM   & \CM   \\
1545\hline
1546setable                 &               &               &               &               &               &               &               &               &               &               & \CM   & \CM   & \CM   \\
1547\hline
1548auto-init               &               &               &               &               &               &               &               &               &               &               & \CM   & \CM   & \CM   \\
1549\hline
1550(Un)Scoped              &               &               &               &               &               &               &               &               &               &               & U             & U/S   & U/S   \\
1551\hline
1552overload                &               & \CM   &               &               &               &               &               &               &               &               &               & \CM   & \CM   \\
1553\hline
1554switch                  &               &               &               &               &               &               &               &               &               &               & \CM   & \CM   & \CM   \\
1555\hline
1556loop                    &               &               &               &               &               &               &               &               &               &               &               &               & \CM   \\
1557\hline
1558array/subscript &               &               &               &               &               &               &               &               &               &               & \CM   &               & \CM   \\
1559\hline
1560subtype                 &               &               &               &               &               &               &               &               &               &               &               &               & \CM   \\
1561\hline
1562inheritance             &               &               &               &               &               &               &               &               &               &               &               &               & \CM   \\
1563\end{tabular}
1564\end{table}
Note: See TracBrowser for help on using the repository browser.