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

Last change on this file since f5dbc8d was 29c8675, checked in by JiadaL <j82liang@…>, 13 months ago

update thesis

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