source: doc/theses/jiada_liang_MMath/relatedwork.tex @ 924534e

Last change on this file since 924534e was 924534e, checked in by Peter A. Buhr <pabuhr@…>, 4 months ago

more proofreading on the enumeration related-work section

  • Property mode set to 100644
File size: 38.2 KB
Line 
1\chapter{Related Work}
2\label{s:RelatedWork}
3
4An enumeration type exist in many popular programming languages, both past and present, \eg Pascal~\cite{Pascal}, Ada~\cite{Ada}, \Csharp~\cite{Csharp}, \CC, Go~\cite{Go}, Java~\cite{Java}, Modula-3~\cite{Modula-3}, Rust~\cite{Rust}, Swift~\cite{Swift}, Python~\cite{Python}, and the algebraic data-type in functional programming.
5Among theses languages, there are a large set of overlapping features, but each language has its own unique extensions and restrictions.
6
7
8\section{Pascal}
9\lstnewenvironment{pascal}[1][]{\lstset{language=pascal,escapechar=\$,moredelim=**[is][\color{red}]{@}{@},}\lstset{#1}}{}
10
11Classic Pascal has the \lstinline[language=pascal]{const} declaration binding a name to a constant literal/expression.
12\begin{pascal}
13const one = 0 + 1;   Vowels = set of (A,E,I,O,U);   NULL = NIL;
14                 PI = 3.14159;   Plus = '+';   Fred = 'Fred';
15\end{pascal}
16The enumerator type is inferred from the constant-expression type.
17There is no notion of an ordered set, modulo the \lstinline[language=pascal]{set of} type.
18
19Free Pascal~\cite[\S~3.1.1]{FreePascal} is a modern, object-oriented version of classic Pascal, with a C-style enumeration type.
20Enumerators must be assigned in ascending numerical order with a constant expression and the range can be non-consecutive.
21\begin{pascal}
22Type EnumType = ( one, two, three, forty @= 40@, fortyone );
23\end{pascal}
24Pseudo-functions @Pred@ and @Succ@ can only be used if the range is consecutive.
25The 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.
26The integral size can be explicitly specified using compiler directive @$PACKENUM@~$N$, where $N$ is the number of bytes, \eg:
27\begin{pascal}
28Type @{$\color{red}\$$PACKENUM 1}@ SmallEnum = ( one, two, three );
29            @{$\color{red}\$$PACKENUM 4}@ LargeEnum = ( BigOne, BigTwo, BigThree );
30Var S : SmallEnum; { 1 byte }
31          L : LargeEnum; { 4 bytes}
32\end{pascal}
33
34
35\section{Ada}
36\lstnewenvironment{ada}[1][]{\lstset{language=[2005]Ada,escapechar=\$,moredelim=**[is][\color{red}]{@}{@},literate={'}{\ttfamily'\!}1}\lstset{#1}}{}
37
38An Ada enumeration type is an ordered list of constants, called \Newterm{literals} (enumerators).
39\begin{ada}
40type RGB is ( @Red@, @Green@, Blue ); -- 3 literals (enumerators)
41\end{ada}
42No other enumerators are assignable to objects of this type.
43Enumerators without an explicitly designated constant value are auto-initialized: from left to right, starting at zero or the next explicitly initialized constant, incrementing by 1.
44To explicitly set enumerator values, \emph{all} enumerators must be set in \emph{ascending} order, \ie there is no auto-initialization.
45\begin{ada}
46type RGB is ( Red, Green, Blue );
47@for RGB use ( Red => 10, Green => 20, Blue => 30 );@ -- ascending order
48\end{ada}
49Hence, the position, value, label tuples are:
50\begin{ada}
51(0, 10, RED)  (1, 20, GREEN)  (2, 30, BLUE) 
52\end{ada}
53
54Like C, Ada enumerators are unscoped, \ie enumerators declared inside of an enum are visible (projected) into the enclosing scope.
55Note, Ada is case-\emph{insensitive} so names may appear in multiple forms and still be the same name (a questionable design decision).
56The enumeration operators are the ordering operators, @=@, @<@, @<=@, @=@, @/=@, @>=@, @>@, where the ordering relation is given implicitly by the sequence of enumerators, which is always ascending.
57
58Ada enumerators are overloadable.
59\begin{ada}
60type Traffic_Light is ( @Red@, Yellow, @Green@ );
61\end{ada}
62Like \CFA, Ada uses an advanced type-resolution algorithm, including the left-hand side of assignment, to disambiguate among overloaded names.
63\VRef[Figure]{f:AdaEnumeration} shows how ambiguity is handled using a cast, \eg \lstinline[language=ada]{RGB'(Red)}.
64
65\begin{figure}
66\begin{ada}
67with Ada.Text_IO; use Ada.Text_IO;
68procedure test is
69   type RGB is ( @Red@, Green, Blue );
70   type Traffic_Light is ( @Red@, Yellow, Green );         -- overload
71   procedure @Red@( Colour : RGB ) is begin            -- overload
72       Put_Line( "Colour is " & RGB'Image( Colour ) );
73   end Red;
74   procedure @Red@( TL : Traffic_Light ) is begin       -- overload
75       Put_Line( "Light is " & Traffic_Light'Image( TL ) );
76   end Red;
77begin
78    @Red@( Blue );                               -- RGB
79    @Red@( Yellow );                            -- Traffic_Light
80    @Red@( @RGB'(Red)@ );               -- ambiguous without cast
81end test;
82\end{ada}
83\caption{Ada Enumeration Overload Resolution}
84\label{f:AdaEnumeration}
85\end{figure}
86
87Ada provides an alias mechanism, \lstinline[language=ada]{renames}, for aliasing types, which is useful to shorten package names.
88\begin{ada}
89OtherRed : RGB renames Red;
90\end{ada}
91which suggests a possible \CFA extension to @typedef@.
92\begin{cfa}
93typedef RGB.Red OtherRed;
94\end{cfa}
95
96There are three pairs of inverse enumeration pseudo-functions (attributes): @'Pos@ and @'Val@, @'Enum_Rep@ and @'Enum_Val@, and @'Image@ and @'Value@,
97\begin{cquote}
98\lstDeleteShortInline@
99\setlength{\tabcolsep}{15pt}
100\begin{tabular}{@{}ll@{}}
101\begin{ada}
102RGB'Pos( Red ) = 0;
103RGB'Enum_Rep( Red ) = 10;
104RGB'Image( Red ) = "RED";
105\end{ada}
106&
107\begin{ada}
108RGB'Val( 0 ) = Red
109RGB'Enum_Val( 10 ) =  Red
110RGB'Value( "Red" ) =  Red
111\end{ada}
112\end{tabular}
113\lstMakeShortInline@
114\end{cquote}
115These attributes are important for IO.
116An 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.
117
118Ada allows the enumerator label to be a character constant.
119\begin{ada}
120type Operator is ( '+', '-', '*', '/' );
121Op : Operator;
122\end{ada}
123which is syntactic sugar for the label and not character literals from the predefined type @Character@.
124The purpose is readability using character literals rather than names.
125\begin{ada}
126Op := '+';
127case Op is                    -- all enumerators must appear
128        when '+' => ... ;
129        when '-' => ... ;
130        when '*' => ... ;
131        when '/' => ... ;
132end case;
133\end{ada}
134Arrays of character enumerators can be treated as strings.
135\begin{ada}
136Ops : array( 0..3 ) of Operator;
137Ops := @"+-*/"@;            -- string assignment to array elements
138Ops := @"+-" & "*/"@;   -- string concatenation and assignment
139for Op of Ops loop
140        Put_Line( Operator'Image( Op ) );
141end loop;
142\end{ada}
143Ada's @Character@ type is defined as a character enumeration across all Latin-1 characters.
144
145Ada's boolean type is defined as a special enumeration, which can be used in conditions.
146\begin{ada}
147type Boolean is (False, True); -- False / True not keywords
148@Flag@ : Boolean;
149if @Flag@ then ...    -- conditional
150\end{ada}
151Since only types derived from @Boolean@ can be a conditional, @Boolean@ is essentially  a builtin type.
152
153Ada provides \emph{consecutive} subtyping of an enumeration using \lstinline[language=ada]{range}.
154\begin{ada}
155type Week is ( Mon, Tue, Wed, Thu, Fri, Sat, Sun );
156subtype Weekday is Week @range Mon .. Fri@;
157subtype Weekend is Week @range Sat .. Sun@;
158Day : Week;
159\end{ada}
160Hence, the ordering of the enumerators is crucial to provide the necessary ranges.
161
162An enumeration type can be used in the Ada \lstinline[language=ada]{case} (switch) and iterating constructs.
163\begin{cquote}
164\lstDeleteShortInline@
165\setlength{\tabcolsep}{15pt}
166\begin{tabular}{@{}ll@{}}
167\begin{ada}
168case Day is
169        when @Mon .. Fri@ => ... ;
170        when @Sat .. Sun@ => ... ;
171end case;
172\end{ada}
173&
174\begin{ada}
175case Day is
176        when @Weekday@ => ... ;  -- subtype ranges
177        when @Weekend@ => ... ;
178end case;
179\end{ada}
180\end{tabular}
181\end{cquote}
182
183\begin{cquote}
184\setlength{\tabcolsep}{12pt}
185\begin{tabular}{@{}lll@{}}
186\begin{ada}
187for Day in @Mon .. Sun@ loop
188        ...
189end loop;
190\end{ada}
191&
192\begin{ada}
193for Day in @Weekday@ loop
194        ...
195end loop;
196\end{ada}
197&
198\begin{ada}
199for Day in @Weekend@ loop
200        ...
201end loop;
202\end{ada}
203\end{tabular}
204\lstMakeShortInline@
205\end{cquote}
206
207An enumeration type can be used as an array dimension and subscript.
208\begin{ada}
209Lunch : array( @Week@ ) of Time;
210for Day in Week loop
211        Lunch( @Day@ ) := ... ;       -- set lunch time
212end loop;
213\end{ada}
214
215
216\section{\CC}
217\label{s:C++RelatedWork}
218\lstnewenvironment{c++}[1][]{\lstset{language=[GNU]C++,escapechar=\$,moredelim=**[is][\color{red}]{@}{@},}\lstset{#1}}{}
219
220\CC is largely backwards compatible with C, so it inherited C's enumerations.
221However, the following non-backwards compatible changes have been made.
222
223\begin{cquote}
2247.2 Change: \CC objects of enumeration type can only be assigned values of the same enumeration type.
225In C, objects of enumeration type can be assigned values of any integral type. \\
226Example:
227\begin{c++}
228enum color { red, blue, green };
229color c = 1;                                                    $\C{// valid C, invalid C++}$
230\end{c++}
231\textbf{Rationale}: The type-safe nature of \CC. \\
232\textbf{Effect on original feature}: Deletion of semantically well-defined feature. \\
233\textbf{Difficulty of converting}: Syntactic transformation. (The type error produced by the assignment can be automatically corrected by applying an explicit cast.) \\
234\textbf{How widely used}: Common.
235\end{cquote}
236
237\begin{cquote}
2387.2 Change: In \CC, the type of an enumerator is its enumeration.
239In C, the type of an enumerator is @int@. \\
240Example:
241\begin{c++}
242enum e { A };
243sizeof(A) == sizeof(int)                                $\C{// in C}$
244sizeof(A) == sizeof(e)                                  $\C{// in C++}$
245/* and sizeof(int) is not necessary equal to sizeof(e) */
246\end{c++}
247\textbf{Rationale}: In \CC, an enumeration is a distinct type. \\
248\textbf{Effect on original feature}: Change to semantics of well-defined feature. \\
249\textbf{Difficulty of converting}: Semantic transformation. \\
250\textbf{How widely used}: Seldom. The only time this affects existing C code is when the size of an enumerator is taken.
251Taking the size of an enumerator is not a common C coding practice.
252\end{cquote}
253
254Hence, the values in a \CC enumeration can only be its enumerators (without a cast).
255While the storage size of an enumerator is up to the compiler, there is still an implicit cast to @int@.
256\begin{c++}
257enum E { A, B, C };
258E e = A;
259int i = A;   i = e;                                             $\C{// implicit casts to int}$
260\end{c++}
261\CC{11} added a scoped enumeration, \lstinline[language=c++]{enum class} (or \lstinline[language=c++]{enum struct}), where the enumerators are accessed using type qualification.
262\begin{c++}
263enum class E { A, B, C };
264E e = @E::@A;                                                   $\C{// qualified enumerator}$
265e = B;                                                                  $\C{// B not in scope}$
266\end{c++}
267\CC{20} supports explicit unscoping with a \lstinline[language=c++]{using enum} declaration.
268\begin{c++}
269enum class E { A, B, C };
270@using enum E;@
271E e = A;                                                                $\C{// direct access}$
272e = B;                                                                  $\C{// direct access}$
273\end{c++}
274\CC{11} added the ability to explicitly declare the underlying \emph{integral} type for \lstinline[language=c++]{enum class}.
275\begin{c++}
276enum class RGB @: long@ { Red, Green, Blue };
277enum class rgb @: char@ { Red = 'r', Green = 'g', Blue = 'b' };
278enum class srgb @: signed char@ { Red = -1, Green = 0, Blue = 1 };
279\end{c++}
280There is no implicit conversion from the \lstinline[language=c++]{enum class} type and to its declared type.
281\begin{c++}
282rgb crgb = rgb::Red;
283char ch = rgb::Red;   ch = crgb;                $\C{// disallowed}$
284\end{c++}
285Finally, there is no mechanism to iterate through an enumeration nor use the enumeration type to declare an array dimension.
286
287
288\section{C\raisebox{-0.7ex}{\LARGE$^\sharp$}\xspace} % latex bug: cannot use \relsize{2} so use \LARGE
289\label{s:Csharp}
290\lstnewenvironment{csharp}[1][]{\lstset{language=[Sharp]C,escapechar=\$,moredelim=**[is][\color{red}]{@}{@},}\lstset{#1}}{}
291
292% https://www.tutorialsteacher.com/codeeditor?cid=cs-mk8Ojx
293
294\Csharp is a dynamically-typed programming-language with a scoped, integral enumeration-type similar to C/\CC enumeration.
295\begin{csharp}
296enum Weekday : byte { Mon, Tue, Wed, Thu@ = 10@, Fri, Sat, Sun@,@ };
297\end{csharp}
298The default underlying type is @int@, with auto-incrementing, implicit/explicit initialization, terminator comma, and optional integral typing (default @int@)
299A method cannot be defined in an enumeration type.
300As well, there is an explicit bidirectional conversion between an enumeration and its integral type, and an implicit conversion to the enumerator label in display contexts.
301\begin{csharp}
302int day = (int)Weekday.Fri;             $\C{// day == 10}$
303Weekday weekday = (Weekdays)42;         $\C{// weekday == 42, logically invalid}$
304Console.WriteLine( Weekday.Fri ); $\C{// print Fri}$
305string mon = Weekday.Mon.ToString(); $\C{// mon == "Mon"}$
306\end{csharp}
307
308The @Enum.GetValues@ pseudo-method retrieves an array of the enumeration constants for looping over an enumeration type or variable.
309\begin{csharp}
310foreach ( Weekday constant in @Enum.GetValues@( typeof(Weekday) ) ) {
311        Console.WriteLine( constant + " " + (int)constant ); // label, position
312}
313\end{csharp}
314
315The @Flags@ attribute creates a bit-flags enumeration, allowing bitwise operators @&@, @|@, @~@ (complement), @^@ (xor).
316\begin{csharp}
317@[Flags]@ public enum Weekday {
318        None = 0x0, Mon = 0x1, Tue = 0x2, Wed = 0x4,
319        Thu = 0x8, Fri = 0x10, Sat = 0x20, Sun = 0x40,
320        Weekend = @Sat | Sun@,
321        Weekdays = @Mon | Tue | Wed | Thu | Fri@
322}
323Weekday meetings = @Weekday.Mon | Weekday.Wed@; // 0x5
324\end{csharp}
325
326\VRef[Figure]{CsharpFreeVersusClass} shows an enumeration with free routines for manipulation, and embedding the enumeration and operations into an enumeration class.
327The key observation is that an enumeration class is just a structuring mechanism without any additional semantics.
328
329% https://learn.microsoft.com/en-us/dotnet/api/system.enum?view=net-8.0
330
331\begin{figure}
332\centering
333\lstDeleteShortInline@
334\begin{tabular}{@{}l|l@{}}
335\multicolumn{1}{@{}c|}{non-object oriented} & \multicolumn{1}{c@{}}{object oriented} \\
336\hline
337\begin{csharp}
338public class Program {
339
340        enum Weekday {
341                Mon, Tue, Wed, Thu, Fri, Sat, Sun };
342
343
344        static bool isWeekday( Weekday wd ) {
345                return Weekday.Mon <= wd
346                        && wd <= Weekday.Fri;
347        }
348        static bool isWeekend( Weekday wd ) {
349                return Weekday.Sat <= wd
350                        && wd <= Weekday.Sun;
351        }
352
353
354        public static void Main() {
355                Weekday day = Weekday.Sat;
356
357                Console.WriteLine( isWeekday( day ) );
358                Console.WriteLine( isWeekend( day ) );
359        }
360}
361\end{csharp}
362&
363\begin{csharp}
364public class Program {
365        public @class@ WeekDay {
366                public enum Weekday {
367                        Mon=-4, Tue=-3, Wed=-2, Thu=-1,
368                        Fri=0, Sat=1, Sun=2 };
369                Weekday day;
370                public bool isWeekday() {
371                        return day <= 0;
372
373                }
374                public bool isWeekend() {
375                        return day > 0
376
377                }
378                public WeekDay( Weekday d ) { day = d; }
379        }
380        public static void Main() {
381                WeekDay cday = new
382                                WeekDay( WeekDay.Weekday.Sat );
383                Console.WriteLine( cday.isWeekday() );
384                Console.WriteLine( cday.isWeekend() );
385        }
386}
387\end{csharp}
388\end{tabular}
389\lstMakeShortInline@
390\caption{\Csharp: Free Routine Versus Class Enumeration}
391\label{CsharpFreeVersusClass}
392\end{figure}
393
394
395\section{Golang}
396\lstnewenvironment{Go}[1][]{\lstset{language=Go,escapechar=\$,moredelim=**[is][\color{red}]{@}{@},}\lstset{#1}}{}
397
398Golang provides a mechanism similar to classic Pascal \lstinline[language=pascal]{const}, binding a name to a constant literal/expression (pseudo enumeration).
399\begin{Go}
400const ( R = 0; G; B )                                   $\C{// implicit: 0 0 0}$
401const ( Fred = "Fred"; Mary = "Mary"; Jane = "Jane" ) $\C{// explicit: Fred Mary Jane}$
402const ( S = 0; T; USA = "USA"; U; V = 3.1; W ) $\C{// type change, implicit/explicit: 0 0 USA USA 3.1 3.1}$
403\end{Go}
404Constant names are unscoped and must be unique (no overloading).
405The first enumerator \emph{must} be explicitly initialized;
406subsequent enumerators can be implicitly or explicitly initialized.
407Implicit initialization is the previous (predecessor) enumerator value.
408
409Auto-incrementing is supported by the keyword \lstinline[language=Go]{iota}, available only in the \lstinline[language=Go]{const} declaration.
410The \lstinline[language=Go]{iota} is a \emph{per \lstinline[language=golang]{const} declaration} integer counter, starting at zero and implicitly incremented by one for each \lstinline[language=golang]{const} identifier (enumerator).
411\begin{Go}
412const ( R = @iota@; G; B )                              $\C{// implicit: 0 1 2}$
413const ( C = @iota + B + 1@; G; Y )              $\C{// implicit: 3 4 5}$
414\end{Go}
415An underscore \lstinline[language=golang]{const} identifier advances \lstinline[language=Go]{iota}.
416\begin{Go}
417const ( O1 = iota + 1; @_@; O3; @_@; O5 ) // 1, 3, 5 
418\end{Go}
419Auto-incrementing stops after an explicit initialization.
420\begin{Go}
421const ( Mon = iota; Tue; Wed; // 0, 1, 2
422         @Thu = 10@; Fri; Sat; Sun ) // 10, 10, 10, 10
423\end{Go}
424Auto-incrementing can be restarted with an expression containing \emph{one} \lstinline[language=Go]{iota}.
425\begin{Go}
426const ( V1 = iota; V2; @V3 = 7;@ V4 = @iota@; V5 ) // 0 1 7 3 4
427const ( Mon = iota; Tue; Wed; // 0, 1, 2
428         @Thu = 10;@ Fri = @iota - Wed + Thu - 1@; Sat; Sun ) // 10, 11, 12, 13
429\end{Go}
430Note, \lstinline[language=Go]{iota} is advanced for an explicitly initialized enumerator, like the underscore @_@ identifier.
431
432Basic switch and looping are possible.
433\begin{cquote}
434\lstDeleteShortInline@
435\setlength{\tabcolsep}{15pt}
436\begin{tabular}{@{}ll@{}}
437\begin{Go}
438day := Mon;
439switch day {
440  case Mon, Tue, Wed, Thu, Fri:
441        fmt.Println( "weekday" );
442  case Sat, Sun:
443        fmt.Println( "weekend" );
444}
445\end{Go}
446&
447\begin{Go}
448
449for i := Mon; i <= Sun; i += 1 {
450    fmt.Println( i )
451}
452
453
454
455\end{Go}
456\end{tabular}
457\lstMakeShortInline@
458\end{cquote}
459The loop prints the values from 0 to 13 because there is no actual enumeration.
460
461
462\section{Java}
463\lstnewenvironment{Java}[1][]{\lstset{language=Java,escapechar=\$,moredelim=**[is][\color{red}]{!}{!},}\lstset{#1}}{}
464
465Every enumeration in Java is an enumeration class.
466For a basic enumeration
467\begin{Java}
468enum Weekday { Mon, Tue, Wed, Thu, Fri, Sat, Sun };
469Weekday day = Weekday.Sat;
470\end{Java}
471the scoped enumerators are an ordered list of @final@ methods of type integer, ordered left to right starting at 0, increasing by 1.
472The value of an enumeration instance is restricted to the enumeration's enumerators.
473There is an implicit integer variable in the enumeration used to store the value of an enumeration instance.
474The position (ordinal) and label are accessible, and the value is the same as the position.
475\begin{Java}
476System.out.println( !day.ordinal()! + " " + !day! ); // 5 Sat
477\end{Java}
478There are no implicit conversions to/from an enumerator and its underlying type.
479
480To explicitly assign enumerator values, the enumeration must specify an explicit type in the enumeration class.
481\begin{Java}
482enum Weekday {
483        Mon( -4 ), Tue( -3 ), Wed( -2 ), Thu( -1 ), Fri( 0 ), Sat( 1 ), Sun( 2 ); // must appear first
484        private int day;                                        $\C{// underlying enumeration type}$
485        private Weekday( int d ) { day = d; } $\C{// used to initialize enumerators and instances}$
486};
487Weekday day = Weekday.Sat;                              $\C{// implicit constructor call}$
488\end{Java}
489The position, value, and label are accessible.
490\begin{Java}
491System.out.println( !day.ordinal()! + " " + !day.day! + " " + !day! )// 5 1 Sat
492\end{Java}
493The constructor is private so only initialization or assignment can be used to set an enumeration, which ensures only corresponding enumerator values are allowed.
494
495Like \Csharp, \VRef[Figure]{f:JavaFreeVersusClass} shows the same example for an enumeration with free routines for manipulation, and embedding the enumeration and operations into an enumeration class.
496
497\begin{figure}
498\centering
499\lstDeleteShortInline@
500\begin{tabular}{@{}l|l@{}}
501\multicolumn{1}{@{}c|}{non-object oriented} & \multicolumn{1}{c@{}}{object oriented} \\
502\hline
503\begin{Java}
504public class test {
505
506        enum Weekday {
507                Mon, Tue, Wed, Thu, Fri, Sat, Sun };
508
509        static boolean isWeekday( Weekday wd ) {
510                return Weekday.Mon.ordinal() <= wd.ordinal()
511                        && wd.ordinal() <= Weekday.Fri.ordinal();
512        }
513        static boolean isWeekend( Weekday wd ) {
514                return Weekday.Sat.ordinal() <= wd.ordinal()
515                        && wd.ordinal() <= Weekday.Sun.ordinal();
516        }
517
518
519        public static void main( String[] args ) {
520                Weekday day = Weekday.Sat;
521                System.out.println( isWeekday( day ) );
522                System.out.println( isWeekend( day ) );
523        }
524}
525\end{Java}
526&
527\begin{Java}
528public class test {
529        public !enum! WeekDay {
530                Mon(-4), Tue(-3), Wed(-2), Thu(-1),
531                        Fri(0), Sat(1), Sun(2);
532                private int day;
533                public boolean isWeekday() {
534                        return day <= 0;
535
536                }
537                public boolean isWeekend() {
538                        return day > 0;
539
540                }
541                private WeekDay( int d ) { day = d; }
542        }
543        public static void main( String[] args ) {
544                WeekDay day = WeekDay.Sat;
545                System.out.println( day.isWeekday() );
546                System.out.println( day.isWeekend() );
547        }
548}
549\end{Java}
550\end{tabular}
551\lstMakeShortInline@
552\caption{Java: Free Routine Versus Class Enumeration}
553\label{f:JavaFreeVersusClass}
554\end{figure}
555
556An enumeration can appear in a @switch@ statement, but no ranges.
557\begin{Java}
558switch ( day ) {
559  case Mon: case Tue: case Wed: case Thu: case Fri:
560        System.out.println( "weekday" );
561        break;
562  case Sat: case Sun:
563        System.out.println( "weekend" );
564        break;
565}
566\end{Java}
567Looping over an enumeration is done using method @values@, which returns the array of enumerator values.
568\begin{Java}
569for ( Weekday iday : Weekday.values() ) {
570        System.out.println( iday.ordinal() + " " + iday + " " );
571}
572\end{Java}
573
574As well, 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.
575There is also a specialized version of @HashMap@ with enumerator keys, which has performance benefits.
576
577Enumeration inheritence is disallowed because an enumeration is @final@.
578
579
580
581\section{Modula-3}
582
583\section{Rust}
584
585
586\section{Swift}
587\lstnewenvironment{swift}[1][]{\lstset{language=Swift,escapechar=\$,moredelim=**[is][\color{red}]{@}{@},}\lstset{#1}}{}
588
589Model custom types that define a list of possible values.
590
591An enumeration defines a common type for a group of related values and enables you to work with those values in a type-safe way within your code.
592
593If you are familiar with C, you will know that C enumerations assign related names to a set of integer values.
594Enumerations in Swift are much more flexible, and don't have to provide a value for each case of the enumeration.
595If a value (known as a raw value) is provided for each enumeration case, the value can be a string, a character, or a value of any integer or floating-point type.
596
597Alternatively, enumeration cases can specify associated values of any type to be stored along with each different case value, much as unions or variants do in other languages.
598You can define a common set of related cases as part of one enumeration, each of which has a different set of values of appropriate types associated with it.
599
600Enumerations in Swift are first-class types in their own right.
601They adopt many features traditionally supported only by classes, such as computed properties to provide additional information about the enumeration's current value, and instance methods to provide functionality related to the values the enumeration represents.
602Enumerations can also define initializers to provide an initial case value;
603can be extended to expand their functionality beyond their original implementation; and can conform to protocols to provide standard functionality.
604
605For more about these capabilities, see Properties, Methods, Initialization, Extensions, and Protocols.
606
607\paragraph{Enumeration Syntax}
608
609You introduce enumerations with the @enum@ keyword and place their entire definition within a pair of braces:
610\begin{swift}
611enum SomeEnumeration {
612        // enumeration definition goes here
613}
614\end{swift}
615Here's an example for the four main points of a compass:
616\begin{swift}
617enum CompassPoint {
618        case north
619        case south
620        case east
621        case west
622}
623\end{swift}
624The values defined in an enumeration (such as @north@, @south@, @east@, and @west@) are its enumeration cases.
625You use the @case@ keyword to introduce new enumeration cases.
626
627Note:
628Swift enumeration cases don't have an integer value set by default, unlike languages like C and Objective-C.
629In the CompassPoint example above, @north@, @south@, @east@ and @west@ don't implicitly equal 0, 1, 2 and 3.
630Instead, the different enumeration cases are values in their own right, with an explicitly defined type of CompassPoint.
631
632Multiple cases can appear on a single line, separated by commas:
633\begin{swift}
634enum Planet {
635        case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
636}
637\end{swift}
638Each enumeration definition defines a new type.
639Like other types in Swift, their names (such as @CompassPoint@ and @Planet@) start with a capital letter.
640Give enumeration types singular rather than plural names, so that they read as self-evident:
641\begin{swift}
642var directionToHead = CompassPoint.west
643\end{swift}
644The type of @directionToHead@ is inferred when it's initialized with one of the possible values of @CompassPoint@.
645Once @directionToHead@ is declared as a @CompassPoint@, you can set it to a different @CompassPoint@ value using a shorter dot syntax:
646\begin{swift}
647directionToHead = .east
648\end{swift}
649The type of @directionToHead@ is already known, and so you can drop the type when setting its value.
650This makes for highly readable code when working with explicitly typed enumeration values.
651
652\paragraph{Matching Enumeration Values with a Switch Statement}
653
654You can match individual enumeration values with a switch statement:
655\begin{swift}
656directionToHead = .south
657switch directionToHead {
658case .north:
659        print("Lots of planets have a north")
660case .south:
661        print("Watch out for penguins")
662case .east:
663        print("Where the sun rises")
664case .west:
665        print("Where the skies are blue")
666}
667// Prints "Watch out for penguins"
668\end{swift}
669You can read this code as:
670\begin{quote}
671"Consider the value of directionToHead.
672In the case where it equals @.north@, print "Lots of planets have a north".
673In the case where it equals @.south@, print "Watch out for penguins"."
674
675...and so on.
676\end{quote}
677As described in Control Flow, a switch statement must be exhaustive when considering an enumeration's cases.
678If the case for @.west@ is omitted, this code doesn't compile, because it doesn't consider the complete list of @CompassPoint@ cases.
679Requiring exhaustiveness ensures that enumeration cases aren't accidentally omitted.
680
681When it isn't appropriate to provide a case for every enumeration case, you can provide a default case to cover any cases that aren't addressed explicitly:
682\begin{swift}
683let somePlanet = Planet.earth
684switch somePlanet {
685case .earth:
686        print("Mostly harmless")
687default:
688        print("Not a safe place for humans")
689}
690// Prints "Mostly harmless"
691\end{swift}
692
693\paragraph{Iterating over Enumeration Cases}
694
695For some enumerations, it's useful to have a collection of all of that enumeration's cases.
696You enable this by writing @CaseIterable@ after the enumeration's name.
697Swift exposes a collection of all the cases as an allCases property of the enumeration type.
698Here's an example:
699\begin{swift}
700enum Beverage: CaseIterable {
701        case coffee, tea, juice
702}
703let numberOfChoices = Beverage.allCases.count
704print("\(numberOfChoices) beverages available")
705// Prints "3 beverages available"
706\end{swift}
707In the example above, you write @Beverage.allCases@ to access a collection that contains all of the cases of the @Beverage@ enumeration.
708You can use @allCases@ like any other collection -- the collection's elements are instances of the enumeration type, so in this case they're Beverage values.
709The example above counts how many cases there are, and the example below uses a for-in loop to iterate over all the cases.
710\begin{swift}
711for beverage in Beverage.allCases {
712        print(beverage)
713}
714// coffee
715// tea
716// juice
717\end{swift}
718The syntax used in the examples above marks the enumeration as conforming to the @CaseIterable@ protocol.
719For information about protocols, see Protocols.
720
721\paragraph{Associated Values}
722The examples in the previous section show how the cases of an enumeration are a defined (and typed) value in their own right.
723You can set a constant or variable to Planet.earth, and check for this value later.
724However, it's sometimes useful to be able to store values of other types alongside these case values.
725This additional information is called an associated value, and it varies each time you use that case as a value in your code.
726
727You can define Swift enumerations to store associated values of any given type, and the value types can be different for each case of the enumeration if needed.
728Enumerations similar to these are known as discriminated unions, tagged unions, or variants in other programming languages.
729
730For example, suppose an inventory tracking system needs to track products by two different types of barcode.
731Some products are labeled with 1D barcodes in UPC format, which uses the numbers 0 to 9.
732Each barcode has a number system digit, followed by five manufacturer code digits and five product code digits.
733These are followed by a check digit to verify that the code has been scanned correctly:
734
735Other products are labeled with 2D barcodes in QR code format, which can use any ISO 8859-1 character and can encode a string up to 2,953 characters long:
736
737It's convenient for an inventory tracking system to store UPC barcodes as a tuple of four integers, and QR code barcodes as a string of any length.
738
739In Swift, an enumeration to define product barcodes of either type might look like this:
740\begin{swift}
741enum Barcode {
742        case upc(Int, Int, Int, Int)
743        case qrCode(String)
744}
745\end{swift}
746This can be read as:
747\begin{quote}
748"Define an enumeration type called Barcode, which can take either a value of upc with an associated value of type @(Int, Int, Int, Int)@, or a value of @qrCode@ with an associated value of type @String@."
749\end{quote}
750This definition doesn't provide any actual @Int@ or @String@ values -- it just defines the type of associated values that Barcode constants and variables can store when they're equal to @Barcode.upc@ or @Barcode.qrCode@.
751
752You can then create new barcodes using either type:
753\begin{swift}
754var productBarcode = Barcode.upc(8, 85909, 51226, 3)
755\end{swift}
756This example creates a new variable called @productBarcode@ and assigns it a value of @Barcode.upc@ with an associated tuple value of @(8, 85909, 51226, 3)@.
757
758You can assign the same product a different type of barcode:
759\begin{swift}
760productBarcode = .qrCode("ABCDEFGHIJKLMNOP")
761\end{swift}
762At this point, the original @Barcode.upc@ and its integer values are replaced by the new @Barcode.qrCode@ and its string value.
763Constants and variables of type Barcode can store either a @.upc@ or a @.qrCode@ (together with their associated values), but they can store only one of them at any given time.
764
765You can check the different barcode types using a switch statement, similar to the example in Matching Enumeration Values with a Switch Statement.
766This time, however, the associated values are extracted as part of the switch statement.
767You extract each associated value as a constant (with the let prefix) or a variable (with the var prefix) for use within the switch case's body:
768\begin{swift}
769switch productBarcode {
770case .upc(let numberSystem, let manufacturer, let product, let check):
771        print("UPC: \(numberSystem), \(manufacturer), \(product), \(check).")
772case .qrCode(let productCode):
773        print("QR code: \(productCode).")
774}
775// Prints "QR code: ABCDEFGHIJKLMNOP."
776\end{swift}
777If all of the associated values for an enumeration case are extracted as constants, or if all are extracted as variables, you can place a single let or var annotation before the case name, for brevity:
778\begin{swift}
779switch productBarcode {
780case let .upc(numberSystem, manufacturer, product, check):
781        print("UPC : \(numberSystem), \(manufacturer), \(product), \(check).")
782case let .qrCode(productCode):
783        print("QR code: \(productCode).")
784}
785// Prints "QR code: ABCDEFGHIJKLMNOP."
786\end{swift}
787
788\paragraph{Raw Values}
789
790The barcode example in Associated Values shows how cases of an enumeration can declare that they store associated values of different types.
791As an alternative to associated values, enumeration cases can come prepopulated with default values (called raw values), which are all of the same type.
792
793Here's an example that stores raw ASCII values alongside named enumeration cases:
794\begin{swift}
795enum ASCIIControlCharacter: Character {
796        case tab = "\t"
797        case lineFeed = "\n"
798        case carriageReturn = "\r"
799}
800\end{swift}
801Here, the raw values for an enumeration called ASCIIControlCharacter are defined to be of type Character, and are set to some of the more common ASCII control characters.
802Character values are described in Strings and Characters.
803
804Raw values can be strings, characters, or any of the integer or floating-point number types.
805Each raw value must be unique within its enumeration declaration.
806
807Note
808
809Raw values are not the same as associated values.
810Raw values are set to prepopulated values when you first define the enumeration in your code, like the three ASCII codes above.
811The raw value for a particular enumeration case is always the same.
812Associated values are set when you create a new constant or variable based on one of the enumeration's cases, and can be different each time you do so.
813Implicitly Assigned Raw Values
814
815When you're working with enumerations that store integer or string raw values, you don't have to explicitly assign a raw value for each case.
816When you don't, Swift automatically assigns the values for you.
817
818For example, when integers are used for raw values, the implicit value for each case is one more than the previous case.
819If the first case doesn't have a value set, its value is 0.
820
821The enumeration below is a refinement of the earlier Planet enumeration, with integer raw values to represent each planet's order from the sun:
822
823\begin{swift}
824enum Planet: Int {
825        case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
826}
827\end{swift}
828In the example above, Planet.mercury has an explicit raw value of 1, Planet.venus has an implicit raw value of 2, and so on.
829
830When strings are used for raw values, the implicit value for each case is the text of that case's name.
831
832The enumeration below is a refinement of the earlier CompassPoint enumeration, with string raw values to represent each direction's name:
833\begin{swift}
834enum CompassPoint: String {
835        case north, south, east, west
836}
837\end{swift}
838In the example above, CompassPoint.south has an implicit raw value of "south", and so on.
839
840You access the raw value of an enumeration case with its rawValue property:
841\begin{swift}
842let earthsOrder = Planet.earth.rawValue
843// earthsOrder is 3
844
845let sunsetDirection = CompassPoint.west.rawValue
846// sunsetDirection is "west"
847\end{swift}
848
849\paragraph{Initializing from a Raw Value}
850
851If you define an enumeration with a raw-value type, the enumeration automatically receives an initializer that takes a value of the raw value's type (as a parameter called rawValue) and returns either an enumeration case or nil.
852You can use this initializer to try to create a new instance of the enumeration.
853
854This example identifies Uranus from its raw value of 7:
855\begin{swift}
856let possiblePlanet = Planet(rawValue: 7)
857// possiblePlanet is of type Planet? and equals Planet.uranus
858\end{swift}
859Not all possible Int values will find a matching planet, however.
860Because of this, the raw value initializer always returns an optional enumeration case.
861In the example above, possiblePlanet is of type Planet?, or "optional Planet."
862Note
863
864The raw value initializer is a failable initializer, because not every raw value will return an enumeration case.
865For more information, see Failable Initializers.
866
867If you try to find a planet with a position of 11, the optional Planet value returned by the raw value initializer will be nil:
868\begin{swift}
869let positionToFind = 11
870if let somePlanet = Planet(rawValue: positionToFind) {
871        switch somePlanet {
872        case .earth:
873                print("Mostly harmless")
874        default:
875                print("Not a safe place for humans")
876        }
877} else {
878        print("There isn't a planet at position \(positionToFind)")
879}
880// Prints "There isn't a planet at position 11"
881\end{swift}
882This example uses optional binding to try to access a planet with a raw value of 11.
883The statement if let somePlanet = Planet(rawValue: 11) creates an optional Planet, and sets somePlanet to the value of that optional Planet if it can be retrieved.
884In this case, it isn't possible to retrieve a planet with a position of 11, and so the else branch is executed instead.
885
886\paragraph{Recursive Enumerations}
887
888A recursive enumeration is an enumeration that has another instance of the enumeration as the associated value for one or more of the enumeration cases.
889You indicate that an enumeration case is recursive by writing indirect before it, which tells the compiler to insert the necessary layer of indirection.
890
891For example, here is an enumeration that stores simple arithmetic expressions:
892\begin{swift}
893enum ArithmeticExpression {
894        case number(Int)
895        indirect case addition(ArithmeticExpression, ArithmeticExpression)
896        indirect case multiplication(ArithmeticExpression, ArithmeticExpression)
897}
898\end{swift}
899You can also write indirect before the beginning of the enumeration to enable indirection for all of the enumeration's cases that have an associated value:
900\begin{swift}
901indirect enum ArithmeticExpression {
902        case number(Int)
903        case addition(ArithmeticExpression, ArithmeticExpression)
904        case multiplication(ArithmeticExpression, ArithmeticExpression)
905}
906\end{swift}
907This enumeration can store three kinds of arithmetic expressions: a plain number, the addition of two expressions, and the multiplication of two expressions.
908The addition and multiplication cases have associated values that are also arithmetic expressions -- these associated values make it possible to nest expressions.
909For example, the expression (5 + 4) * 2 has a number on the right-hand side of the multiplication and another expression on the left-hand side of the multiplication.
910Because the data is nested, the enumeration used to store the data also needs to support nesting -- this means the enumeration needs to be recursive.
911The code below shows the ArithmeticExpression recursive enumeration being created for (5 + 4) * 2:
912\begin{swift}
913let five = ArithmeticExpression.number(5)
914let four = ArithmeticExpression.number(4)
915let sum = ArithmeticExpression.addition(five, four)
916let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2))
917\end{swift}
918A recursive function is a straightforward way to work with data that has a recursive structure.
919For example, here's a function that evaluates an arithmetic expression:
920\begin{swift}
921func evaluate(_ expression: ArithmeticExpression) -> Int {
922        switch expression {
923        case let .number(value):
924                return value
925        case let .addition(left, right):
926                return evaluate(left) + evaluate(right)
927        case let .multiplication(left, right):
928                return evaluate(left) * evaluate(right)
929        }
930}
931
932print(evaluate(product))
933// Prints "18"
934\end{swift}
935This function evaluates a plain number by simply returning the associated value.
936It evaluates an addition or multiplication by evaluating the expression on the left-hand side, evaluating the expression on the right-hand side, and then adding them or multiplying them.
937
938
939\section{Python}
940
941\section{Algebraic Data Type}
Note: See TracBrowser for help on using the repository browser.