Changes in / [b166b1c:f30be51f]


Ignore:
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • doc/theses/jiada_liang_MMath/CFAenum.tex

    rb166b1c rf30be51f  
    2525
    2626In C, unscoped enumerators present a \newterm{naming problem} when multiple enumeration types appear in the same scope with duplicate enumerator names.
    27 There is no mechanism in C to resolve these naming conflicts other than renaming one of the duplicates, which may be impossible if the conflict comes from system include files.
     27There is no mechanism in C to resolve these naming conflicts other than renaming one of the duplicates, which may be impossible.
    2828
    2929The \CFA type-system allows extensive overloading, including enumerators.
     
    3333enum E1 { First, Second, Third, Fourth };
    3434enum E2 { @Fourth@, @Third@, @Second@, @First@ }; $\C{// same enumerator names}$
    35 E1 f() { return Third; }                                $\C{// overloaded functions, different return types}$
    36 E2 f() { return Fourth; }
     35E1 p() { return Third; }                                $\C{// return}$
     36E2 p() { return Fourth; }
    3737void foo() {
    3838        E1 e1 = First;   E2 e2 = First;         $\C{// initialization}$
    3939        e1 = Second;   e2 = Second;                     $\C{// assignment}$
    40         e1 = f();   e2 = f();                           $\C{// function call}$
     40        e1 = p();   e2 = p();                           $\C{// function call}$
    4141        int i = @E1.@First + @E2.@First;        $\C{// disambiguate with qualification}$
    4242        int j = @(E1)@First + @(E2)@First;      $\C{// disambiguate with cast}$
    4343}
    4444\end{cfa}
    45 \CFA overloading allows programmers to use the most meaningful names without fear of name clashes within a program or from external sources, like include files.
    46 Experience from \CFA developers is that the type system implicitly and correctly disambiguates the majority of overloaded names, \ie it is rare to get an incorrect selection or ambiguity, even among hundreds of overloaded variables and functions.
    47 Any ambiguity can be resolved using qualification or casting.
     45\CFA overloading allows programmers to use the most meaningful names without fear of name clashes from include files.
     46In most cases, the type system implicitly disambiguates, otherwise the programmer explicitly disambiguates using qualification or casting.
    4847
    4948
     
    6463It is possible to toggle back to unscoping using the \CFA @with@ clause/statement (see also \CC \lstinline[language=c++]{using enum} in Section~\ref{s:C++RelatedWork}).
    6564\begin{cfa}
    66 with ( @Week@, @RGB@ ) {                                $\C{// type names}$
    67          week = @Sun@;                                          $\C{// no qualification}$
     65with ( @Week@, @RGB@ ) {                        $\C{// type names}$
     66         week = @Sun@;                                  $\C{// no qualification}$
    6867         rgb = @Green@;
    6968}
    7069\end{cfa}
    71 As in Section~\ref{s:EnumeratorVisibility}, opening multiple scoped enumerations in a @with@ can result in duplicate enumeration names, but \CFA implicit type resolution and explicit qualification/casting handle this localized scenario.
    72 
     70As in Section~\ref{s:EnumeratorVisibility}, opening multiple scoped enumerations in a @with@ can result in duplicate enumeration names, but \CFA implicit type resolution and explicit qualification/casting handle ambiguities.
    7371
    7472\section{Enumeration Trait}
     
    186184% \end{cfa}
    187185% Note the ability to print all of an enumerator's properties.
     186
    188187
    189188
     
    372371
    373372
     373
    374374\section{Enumerated Arrays}
    375375Enumerated array use an \CFA array as their index.
     
    382382sout | "Colour Code of Orange is " | colourCode[Orange];
    383383\end{cfa}
    384 
    385384
    386385\section{Planet Example}
  • doc/theses/jiada_liang_MMath/background.tex

    rb166b1c rf30be51f  
    11\chapter{Background}
    22
    3 \vspace*{-8pt}
    4 
    53\CFA is a backwards-compatible extension of the C programming language, therefore, it must support C-style enumerations.
    6 The following discussion covers C enumerations.
     4The following covers C enumerations.
    75
    86As discussed in \VRef{s:Aliasing}, it is common for C programmers to ``believe'' there are three equivalent forms of named constants.
     
    1816\item
    1917The same explicit management is true for the @const@ declaration, and the @const@ variable cannot appear in constant-expression locations, like @case@ labels, array dimensions,\footnote{
    20 C allows variable-length array-declarations (VLA), so this case does work, but it fails in \CC, which does not support VLAs, unless it is \lstinline{g++}.} immediate oper\-ands of assembler instructions, and occupy storage.
     18C allows variable-length array-declarations (VLA), so this case does work, but it fails in \CC, which does not support VLAs, unless it is \lstinline{g++}.} immediate operands of assembler instructions, and occupy storage.
    2119\begin{clang}
    2220$\$$ nm test.o
     
    2422\end{clang}
    2523\item
    26 Only the @enum@ form is managed by the compiler, is part of the language type-system, works in all C constant-expression locations, and normally does not occupy storage.
     24Only the @enum@ form is managed by the compiler, is part of the language type-system, works in all C constant-expression locations, and might not occupy storage..
    2725\end{enumerate}
    2826
     
    3230
    3331C can simulate the aliasing @const@ declarations \see{\VRef{s:Aliasing}}, with static and dynamic initialization.
    34 \begin{cquote}
    35 \begin{tabular}{@{}l@{}l@{}}
    36 \multicolumn{1}{@{}c@{}}{\textbf{static initialization}} &  \multicolumn{1}{c@{}}{\textbf{dynamic intialization}} \\
    3732\begin{clang}
    38 static const int one = 0 + 1;
     33static const int one = 0 + 1;                   $\C{// static initialization}$
    3934static const void * NIL = NULL;
    4035static const double PI = 3.14159;
    4136static const char Plus = '+';
    4237static const char * Fred = "Fred";
    43 static const int Mon = 0, Tue = Mon + 1, Wed = Tue + 1,
    44         Thu = Wed + 1, Fri = Thu + 1, Sat = Fri + 1, Sun = Sat + 1;
     38static const int Mon = 0, Tue = Mon + 1, Wed = Tue + 1, Thu = Wed + 1, Fri = Thu + 1,
     39                                        Sat = Fri + 1, Sun = Sat + 1;
     40void foo() {
     41        const int r = random() % 100;           $\C{// dynamic intialization}$
     42        int va[r];                                                      $\C{// VLA, auto scope only}$
     43}
    4544\end{clang}
    46 &
    47 \begin{clang}
    48 void foo() {
    49         // auto scope only
    50         const int r = random() % 100;
    51         int va[r];
    52 }
    53 
    54 
    55 \end{clang}
    56 \end{tabular}
    57 \end{cquote}
    58 However, statically initialized identifiers can not appear in constant-expression contexts, \eg @case@.
    59 Dynamically initialized identifiers may appear in initialization and array dimensions in @g++@, which allows variable-sized arrays on the stack.
     45Statically initialized identifiers may appear in any constant-expression context, \eg @case@.
     46Dynamically initialized identifiers may appear as array dimensions in @g++@, which allows variable-sized arrays on the stack.
    6047Again, this form of aliasing is not an enumeration.
    6148
     
    9582The enumerators are rvalues, so assignment is disallowed.
    9683Finally, enumerators are \newterm{unscoped}, \ie enumerators declared inside of an @enum@ are visible (projected) into the enclosing scope of the @enum@ type.
    97 For unnamed enumerations, this semantic is required because there is no type name for scoped qualification.
     84For unnamed enumeration this semantic is required because there is no type name for scoped qualification.
    9885
    9986As noted, this kind of aliasing declaration is not an enumeration, even though it is declared using an @enum@ in C.
    10087While the semantics is misleading, this enumeration form matches with aggregate types:
    10188\begin{cfa}
    102 typedef struct @/* unnamed */@  { ... } S;
    103 struct @/* unnamed */@  { ... } x, y, z;        $\C{// questionable}$
     89typedef struct /* unnamed */  { ... } S;
     90struct /* unnamed */  { ... } x, y, z;  $\C{// questionable}$
    10491struct S {
    105         union @/* unnamed */@ {                                 $\C{// unscoped fields}$
     92        union /* unnamed */ {                           $\C{// unscoped fields}$
    10693                int i;  double d ;  char ch;
    10794        };
     
    145132@week = 10000;@                                         $\C{// UNDEFINED! implicit conversion to Week}$
    146133\end{clang}
    147 While converting an enumerator to its underlying type is useful, the implicit conversion from the base type to an enumeration type is a common source of error.
     134While converting an enumerator to underlying type is useful, the implicit conversion from the base type to an enumeration type is a common source of error.
    148135
    149136Enumerators can appear in @switch@ and looping statements.
     
    156143                printf( "weekend\n" );
    157144}
    158 for ( enum Week day = Mon; day <= Sun; day += 1 ) { // step of 1
     145for ( enum Week day = Mon; day <= Sun; day += 1 ) {
    159146        printf( "day %d\n", day ); // 0-6
    160147}
    161148\end{cfa}
    162 For iterating to make sense, the enumerator values \emph{must} have a consecutive ordering with a fixed step between values.
    163 For example, a gap introduced by @Thu = 10@, results in iterating over the values 0--13, where values 3--9 are not @Week@ values.
     149For iterating, the enumerator values \emph{must} have a consecutive ordering with a fixed step between values.
    164150Note, it is the bidirectional conversion that allows incrementing @day@: @day@ is converted to @int@, integer @1@ is added, and the result is converted back to @Week@ for the assignment to @day@.
    165151For safety, \CC does not support the bidirectional conversion, and hence, an unsafe cast is necessary to increment @day@: @day = (Week)(day + 1)@.
    166152
    167 There is a C idiom to automatically compute the number of enumerators in an enumeration.
     153There is a C idiom to automatically know the number of enumerators in an enumeration.
    168154\begin{cfa}
    169155enum E { A, B, C, D, @N@ };  // N == 4
     
    197183
    198184\bigskip
    199 While C provides a true enumeration, it is restricted, has unsafe semantics, and does provide useful enumeration features in other programming languages.
     185While C provides a true enumeration, it is restricted, has unsafe semantics, and does provide enumeration features in other programming languages.
  • doc/theses/jiada_liang_MMath/intro.tex

    rb166b1c rf30be51f  
    88In theory, there are an infinite set of constant names per type representing an infinite set of values.
    99
    10 It is common in mathematics, engineering, and computer science to alias new constants to existing constants so they have the same value, \eg $\pi$, $\tau$ (2$\pi$), $\phi$ (golden ratio), K(k), M, G, T for powers of 2\footnote{Overloaded with SI powers of 10.} often prefixing bits (b) or bytes (B), \eg Gb, MB, and in general situations, \eg specific times (noon, New Years), cities (Big Apple), flowers (Lily), \etc.
     10It is common in mathematics, engineering and computer science to alias new constants to existing constants so they have the same value, \eg $\pi$, $\tau$ (2$\pi$), $\phi$ (golden ratio), K(k), M, G, T for powers of 2\footnote{Overloaded with SI powers of 10.} often prefixing bits (b) or bytes (B), \eg Gb, MB, and in general situations, \eg specific times (noon, New Years), cities (Big Apple), flowers (Lily), \etc.
    1111An alias can bind to another alias, which transitively binds it to the specified constant.
    1212Multiple aliases can represent the same value, \eg eighth note and quaver, giving synonyms.
     
    8080\end{tabular}
    8181\end{cquote}
    82 Here, the enumeration @Week@ defines the enumerator constants @Mon@, @Tue@, @Wed@, @Thu@, @Fri@, @Sat@, and @Sun@.
     82Here, the enumeration @Week@ defines the enumerator constant @Mon@, @Tue@, @Wed@, @Thu@, @Fri@, @Sat@ and @Sun@.
    8383The implicit ordering implies the successor of @Tue@ is @Mon@ and the predecessor of @Tue@ is @Wed@, independent of any associated enumerator values.
    8484The value is the implicitly/explicitly assigned constant to support any enumeration operations;
     
    204204\begin{cfa}
    205205void foo( void );
    206 struct unit {} u;       $\C[1.5in]{// empty type}$
     206struct unit {} u;  // empty type
    207207unit bar( unit );
    208 foo( foo() );           $\C{// void argument does not match with void parameter}$
    209 bar( bar( u ) );        $\C{// unit argument does match with unit parameter}\CRT$
     208foo( foo() );        // void argument does not match with void parameter
     209bar( bar( u ) );   // unit argument does match with unit parameter
    210210\end{cfa}
    211211
     
    252252
    253253The key observation is the dichotomy between an ADT and enumeration: the ADT uses the associated type resulting in a union-like data structure, and the enumeration does not use the associated type, and hence, is not a union.
    254 While an enumeration is constructed using the ADT mechanism, it is so restricted it is not an ADT.
     254While the enumeration is constructed using the ADT mechanism, it is so restricted it is not an ADT.
    255255Furthermore, a general ADT cannot be an enumeration because the constructors generate different values making enumerating meaningless.
    256256While functional programming languages regularly repurpose the ADT type into an enumeration type, this process seems contrived and confusing.
     
    277277inheritance
    278278\end{enumerate}
    279 
    280 
    281 \begin{comment}
    282 Date: Wed, 1 May 2024 13:41:58 -0400
    283 Subject: Re: Enumeration
    284 To: "Peter A. Buhr" <pabuhr@uwaterloo.ca>
    285 From: Gregor Richards <gregor.richards@uwaterloo.ca>
    286 
    287 I think I have only one comment and one philosophical quibble to make:
    288 
    289 Comment: I really can't agree with putting MB in the same category as the
    290 others. MB is both a quantity and a unit, and the suggestion that MB *is* one
    291 million evokes the rather disgusting comparison 1MB = 1000km.  Unit types are
    292 not in the scope of this work.
    293 
    294 Philosophical quibble: Pi *is* 3.14159...etc. Monday is not 0; associating
    295 Monday with 0 is just a consequence of the language. The way this is written
    296 suggests that the intentional part is subordinate to the implementation detail,
    297 which seems backwards to me. Calling the number "primary" and the name
    298 "secondary" feels like you're looking out from inside of the compiler, instead
    299 of looking at the language from the outside. And, calling secondary values
    300 without visible primary values "opaque"-which yes, I realize is my own term
    301 ;)-suggests that you insist that the primary value is a part of the design, or
    302 at least mental model, of the program. Although as a practical matter there is
    303 some system value associated with the constructor/tag of an ADT, that value is
    304 not part of the mental model, and so calling it "primary" and calling the name
    305 "secondary" and "opaque" seems either (a) very odd or (b) very C-biased. Or
    306 both.
    307 
    308 With valediction,
    309   - Gregor Richards
    310 
    311 
    312 Date: Thu, 30 May 2024 23:15:23 -0400
    313 Subject: Re: Meaning?
    314 To: "Peter A. Buhr" <pabuhr@uwaterloo.ca>
    315 CC: <ajbeach@uwaterloo.ca>, <j82liang@uwaterloo.ca>
    316 From: Gregor Richards <gregor.richards@uwaterloo.ca>
    317 
    318 I have to disagree with this being agreeing to disagree, since we agree
    319 here. My core point was that it doesn't matter whether you enumerate over the
    320 names or the values. This is a distinction without a difference in any case
    321 that matters. If any of the various ways of looking at it are actually
    322 different from each other, then that's because the enumeration has failed to be
    323 an enumeration in some other way, not because of the actual process of
    324 enumeration. Your flag enum is a 1-to-1 map of names and values, so whether you
    325 walk through names or walk through values is not an actual distinction. It
    326 could be distinct in the *order* that it walks through, but that doesn't
    327 actually matter, it's just a choice that has to be made. Walking through entire
    328 range of machine values, including ones that aren't part of the enumeration,
    329 would be bizarre in any case.
    330 
    331 Writing these out has crystallized some thoughts, albeit perhaps not in a way
    332 that's any help to y'all. An enumeration is a set of names; ideally an ordered
    333 set of names. The state of enumerations in programming languages muddies things
    334 because they often expose the machine value underlying those names, resulting
    335 in a possibly ordered set of names and a definitely ordered set of values. And,
    336 muddying things further, because those underlying values are exposed, enums are
    337 used in ways that *depend* on the underlying values being exposed, making that
    338 a part of the definition. But, an enumeration is conceptually just *one* set,
    339 not both. So much of the difficulty is that you're trying to find a way to make
    340 a concept that should be a single set agree with an implementation that's two
    341 sets. If those sets have a 1-to-1 mapping, then who cares, they're just
    342 aliases. It's the possibility of the map being surjective (having multiple
    343 names for the same underlying values) that breaks everything. Personally, I
    344 think that an enum with aliases isn't an enumeration anyway, so who cares about
    345 the rest; if you're not wearing the gourd as a shoe, then it's not an
    346 enumeration.
    347 
    348 With valediction,
    349   - Gregor Richards
    350 \end{comment}
  • doc/theses/jiada_liang_MMath/relatedwork.tex

    rb166b1c rf30be51f  
    4343\begin{pascal}
    4444Type @{$\color{red}\$$PACKENUM 1}@ SmallEnum = ( one, two, three );
    45                 @{$\color{red}\$$PACKENUM 4}@ LargeEnum = ( BigOne, BigTwo, BigThree );
     45            @{$\color{red}\$$PACKENUM 4}@ LargeEnum = ( BigOne, BigTwo, BigThree );
    4646Var S : SmallEnum; { 1 byte }
    4747          L : LargeEnum; { 4 bytes}
     
    406406Mon 0, Tue 1, Wed 2, Thu 10, Fri 11, Sat 12, Sun 13,
    407407\end{csharp}
    408 Hence, enumerating is not supplied directly by the enumeration, but indirectly through another enumerable type, array.
    409408
    410409An enumeration type cannot declare an array dimension but an enumerator can be used as a subscript.
     
    536535\begin{Java}
    537536public boolean isWeekday() { return !ordinal()! <= Fri.ordinal(); }
    538 public boolean isWeekend() { return Sat.ordinal() <= !ordinal()!; }
     537public boolean isWeekend() { return Fri.ordinal() < !ordinal()!; }
    539538\end{Java}
    540539Notice the unqualified calls to @ordinal@ in the members implying a \lstinline[language=Java]{this} to some implicit implementation variable, likely an @int@.
     
    5915900 1 Mon,  1 2 Tue,  2 3 Wed,  3 4 Thu,  4 5 Fri,  5 6 Sat,  6 7 Sun, 
    592591\end{Java}
    593 Like \Csharp, enumerating is supplied indirectly through another enumerable type, not via the enumeration.
    594592
    595593An enumeration type cannot declare an array dimension nor can an enumerator be used as a subscript.
     
    604602% https://doc.rust-lang.org/reference/items/enumerations.html
    605603
    606 Rust @enum@ provides two largely independent mechanisms from a single language feature: an ADT and an enumeration.
     604Rust @enum@ provides two largely independent mechanisms: an ADT and an enumeration.
    607605When @enum@ is an ADT, pattern matching is used to discriminate among the variant types.
    608606\begin{cquote}
    609 \begin{tabular}{@{}l@{\hspace{30pt}}ll@{}}
     607\sf\setlength{\tabcolsep}{20pt}
     608\begin{tabular}{@{}ll@{}}
    610609\begin{rust}
    611610struct S {
    612611        i : isize,  j : isize
    613612}
    614 let mut s = S{ i : 3, j : 4 };
    615613enum @ADT@ {
    616         I( isize ), $\C[1in]{// int}$
    617         F( f64 ),   $\C{// float}$
    618         S( S ),     $\C{// struct}\CRT$
     614        I(isize),   // int
     615        F(f64),   // float
     616        S(S),     // struct
    619617}
    620618\end{rust}
    621619&
    622620\begin{rust}
     621let mut s = S{ i : 3, j : 4 };
    623622let mut adt : ADT;
    624 adt = ADT::I(3);  println!( "{:?}", adt );
    625 adt = ADT::F(3.5);  println!( "{:?}", adt );
    626 adt = ADT::S(s);  println!( "{:?}", adt );
     623adt = ADT::I(3);  adt = ADT::F(3.5);  adt = ADT::S(s); // init examples
    627624@match@ adt {
    628         ADT::I( i ) => println!( "{:}", i ),
    629         ADT::F( f ) => println!( "{:}", f ),
    630         ADT::S( s ) => println!( "{:} {:}", s.i, s.j ),
    631 }
    632 \end{rust}
    633 &
    634 \begin{rust}
    635 I(3)
    636 F(3.5)
    637 S(S { i: 3, j: 4 })
    638 3 4
    639 
    640 
    641 
    642 
    643 
     625        ADT::I(i) => println!( "{:?}", i ),
     626        ADT::F(f) => println!( "{:?}", f ),
     627        ADT::S(s) => println!( "{:?} {:?}", s.i, s.j ),
     628}
    644629\end{rust}
    645630\end{tabular}
    646631\end{cquote}
    647 Even when the variant types are the unit type, the ADT is still not an enumeration because there is no enumerating \see{\VRef{s:AlgebraicDataType}}.
     632When the variant types are the unit type, the ADT is still not an enumeration because there is no enumerating \see{\VRef{s:AlgebraicDataType}}.
    648633\begin{rust}
    649634enum Week { Mon, Tues, Wed, Thu, Fri, Sat, Sun@,@ } // terminating comma
     
    658643However, Rust allows direct setting of the ADT constructor, which means it is actually a tag.
    659644\begin{cquote}
    660 \setlength{\tabcolsep}{15pt}
     645\sf\setlength{\tabcolsep}{15pt}
    661646\begin{tabular}{@{}ll@{}}
    662647\begin{rust}
     
    711696\end{tabular}
    712697\end{cquote}
    713 However, there is no mechanism to iterate through an enumeration without casting to integral and positions versus values is not handled.
     698However, there is no mechanism to iterate through an enumeration without an casting to integral and positions versus values is not handled.
    714699\begin{c++}
    715700for d in Week::Mon as isize ..= Week::Sun as isize {
     
    726711% https://www.programiz.com/swift/online-compiler
    727712
    728 Like Rust, Swift @enum@ provides two largely independent mechanisms from a single language feature: an ADT and an enumeration.
    729 When @enum@ is an ADT, pattern matching is used to discriminate among the variant types.
    730 \begin{cquote}
    731 \setlength{\tabcolsep}{20pt}
    732 \begin{tabular}{@{}l@{\hspace{55pt}}ll@{}}
     713A Swift enumeration provides a heterogenous set of enumerators, like a tagged @union@, where the field name is the enumerator and its list of type parameters form its type.
    733714\begin{swift}
    734 struct S {
    735         var i : Int,  j : Int
    736 }
    737 var s = S( i : 3, j : 5 )
    738 @enum@ ADT {
    739         case I(Int)   $\C[1.125in]{// int}$
    740         case F(Float) $\C{// float}$
    741         case S(S)     $\C{// struct}\CRT$
    742 }
     715enum Many {
     716        case Mon, Tue, Wed, Thu, Fri, Sat, Sun // basic enumerator
     717        case code( String ) // string enumerator
     718        case tuple( Int, Int, Int ) // tuple enumerator
     719};
     720var day = Many.Sat; // qualification to resolve type
     721print( day );
     722day = .Wed // no qualification after type resolved
     723print( day );
     724day = .code( "ABC" );
     725print( day );
     726day = .tuple( 1, 2, 3 );
     727print( day );
     728
     729Sat
     730Wed
     731code("ABC")
     732tuple(1, 2, 3)
    743733\end{swift}
    744 &
     734
     735
     736An 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.
     737
     738If you are familiar with C, you will know that C enumerations assign related names to a set of integer values.
     739Enumerations in Swift are much more flexible, and don't have to provide a value for each case of the enumeration.
     740If 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.
     741
     742Alternatively, 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.
     743You 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.
     744
     745Enumerations in Swift are first-class types in their own right.
     746They 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.
     747Enumerations can also define initializers to provide an initial case value;
     748can be extended to expand their functionality beyond their original implementation; and can conform to protocols to provide standard functionality.
     749
     750For more about these capabilities, see Properties, Methods, Initialization, Extensions, and Protocols.
     751
     752\paragraph{Enumeration Syntax}
     753
     754
     755Note:
     756Swift enumeration cases don't have an integer value set by default, unlike languages like C and Objective-C.
     757In the CompassPoint example above, @north@, @south@, @east@ and @west@ don't implicitly equal 0, 1, 2 and 3.
     758Instead, the different enumeration cases are values in their own right, with an explicitly defined type of CompassPoint.
     759
     760Multiple cases can appear on a single line, separated by commas:
    745761\begin{swift}
    746 var adt : ADT
    747 adt = .I( 3 );  print( adt )
    748 adt = .F( 3.5 );  print( adt )
    749 adt = .S( s );  print( adt )
    750 @switch@ adt {  // pattern matching
    751         case .I(let i):  print( i )
    752         case .F(let f):  print( f )
    753         case .S(let s):  print( s.i, s.j )
     762enum Planet {
     763        case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
    754764}
    755765\end{swift}
    756 &
     766Each enumeration definition defines a new type.
     767Like other types in Swift, their names (such as @CompassPoint@ and @Planet@) start with a capital letter.
     768Give enumeration types singular rather than plural names, so that they read as self-evident:
    757769\begin{swift}
    758 I(3)
    759 F(3.5)
    760 S(S(i: 3, j: 5))
    761 3 5
    762 
    763 
    764 
    765 
    766 
     770var directionToHead = CompassPoint.west
    767771\end{swift}
    768 \end{tabular}
    769 \end{cquote}
    770 (Note, after an @adt@'s type is know, the enumerator is inferred without qualification, \eg @.I(3)@.)
    771 
    772 An enumeration is created when \emph{all} the enumerators are unit-type.
     772The type of @directionToHead@ is inferred when it's initialized with one of the possible values of @CompassPoint@.
     773Once @directionToHead@ is declared as a @CompassPoint@, you can set it to a different @CompassPoint@ value using a shorter dot syntax:
    773774\begin{swift}
    774 enum Week {
    775         case Mon, Tue, Wed, Thu, Fri, Sat, Sun // unit-type
    776 };
    777 var week : Week = Week.Mon;
     775directionToHead = .east
    778776\end{swift}
    779 As well, it is possible to type \emph{all} the enumerators with a common type, and set different values for each enumerator;
    780 for integral types, there is auto-incrementing.
    781 \begin{cquote}
    782 \setlength{\tabcolsep}{15pt}
    783 \begin{tabular}{@{}lll@{}}
     777The type of @directionToHead@ is already known, and so you can drop the type when setting its value.
     778This makes for highly readable code when working with explicitly typed enumeration values.
     779
     780\paragraph{Matching Enumeration Values with a Switch Statement}
     781
     782You can match individual enumeration values with a switch statement:
    784783\begin{swift}
    785 enum WeekInt: @Int@ {
    786         case Mon, Tue, Wed, Thu = 10, Fri,
    787                         Sat = 4, Sun // auto-incrementing
    788 };
     784directionToHead = .south
     785switch directionToHead {
     786case .north:
     787        print("Lots of planets have a north")
     788case .south:
     789        print("Watch out for penguins")
     790case .east:
     791        print("Where the sun rises")
     792case .west:
     793        print("Where the skies are blue")
     794}
     795// Prints "Watch out for penguins"
    789796\end{swift}
    790 &
     797You can read this code as:
     798\begin{quote}
     799"Consider the value of directionToHead.
     800In the case where it equals @.north@, print "Lots of planets have a north".
     801In the case where it equals @.south@, print "Watch out for penguins"."
     802
     803...and so on.
     804\end{quote}
     805As described in Control Flow, a switch statement must be exhaustive when considering an enumeration's cases.
     806If the case for @.west@ is omitted, this code doesn't compile, because it doesn't consider the complete list of @CompassPoint@ cases.
     807Requiring exhaustiveness ensures that enumeration cases aren't accidentally omitted.
     808
     809When 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:
    791810\begin{swift}
    792 enum WeekStr: @String@ {
    793         case Mon = "MON", Tue, Wed, Thu, Fri,
    794                         Sat = "SAT", Sun
    795 };
     811let somePlanet = Planet.earth
     812switch somePlanet {
     813case .earth:
     814        print("Mostly harmless")
     815default:
     816        print("Not a safe place for humans")
     817}
     818// Prints "Mostly harmless"
    796819\end{swift}
    797 \end{tabular}
    798 \end{cquote}
    799 An enumeration only supports equality comparison between enumerator values, unless it inherits from @Comparable@, adding relational operators @<@, @<=@, @>@, and @>=@.
    800 
    801 An enumeration can have methods.
     820
     821\paragraph{Iterating over Enumeration Cases}
     822
     823For some enumerations, it's useful to have a collection of all of that enumeration's cases.
     824You enable this by writing @CaseIterable@ after the enumeration's name.
     825Swift exposes a collection of all the cases as an allCases property of the enumeration type.
     826Here's an example:
    802827\begin{swift}
    803 enum Week: Comparable {
    804         case Mon, Tue, Wed, Thu, Fri, Sat, Sun // unit-type
    805         func @isWeekday() -> Bool@ { return self <= .Fri }    // method
    806         func @isWeekend() -> Bool@ { return .Sat <= self }  // method
    807 };
     828enum Beverage: CaseIterable {
     829        case coffee, tea, juice
     830}
     831let numberOfChoices = Beverage.allCases.count
     832print("\(numberOfChoices) beverages available")
     833// Prints "3 beverages available"
    808834\end{swift}
    809 An enumeration can be used in the @if@ and @switch@ statements, where @switch@ must be exhaustive or have a @default@.
     835In the example above, you write @Beverage.allCases@ to access a collection that contains all of the cases of the @Beverage@ enumeration.
     836You 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.
     837The example above counts how many cases there are, and the example below uses a for-in loop to iterate over all the cases.
     838\begin{swift}
     839for beverage in Beverage.allCases {
     840        print(beverage)
     841}
     842// coffee
     843// tea
     844// juice
     845\end{swift}
     846The syntax used in the examples above marks the enumeration as conforming to the @CaseIterable@ protocol.
     847For information about protocols, see Protocols.
     848
     849\paragraph{Associated Values}
     850The examples in the previous section show how the cases of an enumeration are a defined (and typed) value in their own right.
     851You can set a constant or variable to Planet.earth, and check for this value later.
     852However, it's sometimes useful to be able to store values of other types alongside these case values.
     853This additional information is called an associated value, and it varies each time you use that case as a value in your code.
     854
     855You 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.
     856Enumerations similar to these are known as discriminated unions, tagged unions, or variants in other programming languages.
     857
     858For example, suppose an inventory tracking system needs to track products by two different types of barcode.
     859Some products are labeled with 1D barcodes in UPC format, which uses the numbers 0 to 9.
     860Each barcode has a number system digit, followed by five manufacturer code digits and five product code digits.
     861These are followed by a check digit to verify that the code has been scanned correctly:
     862
     863Other 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:
     864
     865It'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.
     866
     867In Swift, an enumeration to define product barcodes of either type might look like this:
     868\begin{swift}
     869enum Barcode {
     870        case upc(Int, Int, Int, Int)
     871        case qrCode(String)
     872}
     873\end{swift}
     874This can be read as:
     875\begin{quote}
     876"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@."
     877\end{quote}
     878This 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@.
     879
     880You can then create new barcodes using either type:
     881\begin{swift}
     882var productBarcode = Barcode.upc(8, 85909, 51226, 3)
     883\end{swift}
     884This 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)@.
     885
     886You can assign the same product a different type of barcode:
     887\begin{swift}
     888productBarcode = .qrCode("ABCDEFGHIJKLMNOP")
     889\end{swift}
     890At this point, the original @Barcode.upc@ and its integer values are replaced by the new @Barcode.qrCode@ and its string value.
     891Constants 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.
     892
     893You can check the different barcode types using a switch statement, similar to the example in Matching Enumeration Values with a Switch Statement.
     894This time, however, the associated values are extracted as part of the switch statement.
     895You 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:
     896\begin{swift}
     897switch productBarcode {
     898case .upc(let numberSystem, let manufacturer, let product, let check):
     899        print("UPC: \(numberSystem), \(manufacturer), \(product), \(check).")
     900case .qrCode(let productCode):
     901        print("QR code: \(productCode).")
     902}
     903// Prints "QR code: ABCDEFGHIJKLMNOP."
     904\end{swift}
     905If 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:
     906\begin{swift}
     907switch productBarcode {
     908case let .upc(numberSystem, manufacturer, product, check):
     909        print("UPC : \(numberSystem), \(manufacturer), \(product), \(check).")
     910case let .qrCode(productCode):
     911        print("QR code: \(productCode).")
     912}
     913// Prints "QR code: ABCDEFGHIJKLMNOP."
     914\end{swift}
     915
     916\paragraph{Raw Values}
     917
     918The barcode example in Associated Values shows how cases of an enumeration can declare that they store associated values of different types.
     919As an alternative to associated values, enumeration cases can come prepopulated with default values (called raw values), which are all of the same type.
     920
     921Here's an example that stores raw ASCII values alongside named enumeration cases:
     922\begin{swift}
     923enum ASCIIControlCharacter: Character {
     924        case tab = "\t"
     925        case lineFeed = "\n"
     926        case carriageReturn = "\r"
     927}
     928\end{swift}
     929Here, 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.
     930Character values are described in Strings and Characters.
     931
     932Raw values can be strings, characters, or any of the integer or floating-point number types.
     933Each raw value must be unique within its enumeration declaration.
     934
     935Note
     936
     937Raw values are not the same as associated values.
     938Raw values are set to prepopulated values when you first define the enumeration in your code, like the three ASCII codes above.
     939The raw value for a particular enumeration case is always the same.
     940Associated 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.
     941Implicitly Assigned Raw Values
     942
     943When 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.
     944When you don't, Swift automatically assigns the values for you.
     945
     946For example, when integers are used for raw values, the implicit value for each case is one more than the previous case.
     947If the first case doesn't have a value set, its value is 0.
     948
     949The enumeration below is a refinement of the earlier Planet enumeration, with integer raw values to represent each planet's order from the sun:
     950
     951\begin{swift}
     952enum Planet: Int {
     953        case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
     954}
     955\end{swift}
     956In the example above, Planet.mercury has an explicit raw value of 1, Planet.venus has an implicit raw value of 2, and so on.
     957
     958When strings are used for raw values, the implicit value for each case is the text of that case's name.
     959
     960The enumeration below is a refinement of the earlier CompassPoint enumeration, with string raw values to represent each direction's name:
     961\begin{swift}
     962enum CompassPoint: String {
     963        case north, south, east, west
     964}
     965\end{swift}
     966In the example above, CompassPoint.south has an implicit raw value of "south", and so on.
     967
     968You access the raw value of an enumeration case with its rawValue property:
     969\begin{swift}
     970let earthsOrder = Planet.earth.rawValue
     971// earthsOrder is 3
     972
     973let sunsetDirection = CompassPoint.west.rawValue
     974// sunsetDirection is "west"
     975\end{swift}
     976
     977\paragraph{Initializing from a Raw Value}
     978
     979If 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.
     980You can use this initializer to try to create a new instance of the enumeration.
     981
     982This example identifies Uranus from its raw value of 7:
     983\begin{swift}
     984let possiblePlanet = Planet(rawValue: 7)
     985// possiblePlanet is of type Planet? and equals Planet.uranus
     986\end{swift}
     987Not all possible Int values will find a matching planet, however.
     988Because of this, the raw value initializer always returns an optional enumeration case.
     989In the example above, possiblePlanet is of type Planet?, or "optional Planet."
     990Note
     991
     992The raw value initializer is a failable initializer, because not every raw value will return an enumeration case.
     993For more information, see Failable Initializers.
     994
     995If you try to find a planet with a position of 11, the optional Planet value returned by the raw value initializer will be nil:
     996\begin{swift}
     997let positionToFind = 11
     998if let somePlanet = Planet(rawValue: positionToFind) {
     999        switch somePlanet {
     1000        case .earth:
     1001                print("Mostly harmless")
     1002        default:
     1003                print("Not a safe place for humans")
     1004        }
     1005} else {
     1006        print("There isn't a planet at position \(positionToFind)")
     1007}
     1008// Prints "There isn't a planet at position 11"
     1009\end{swift}
     1010This example uses optional binding to try to access a planet with a raw value of 11.
     1011The 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.
     1012In this case, it isn't possible to retrieve a planet with a position of 11, and so the else branch is executed instead.
     1013
     1014\paragraph{Recursive Enumerations}
     1015
     1016A recursive enumeration is an enumeration that has another instance of the enumeration as the associated value for one or more of the enumeration cases.
     1017You indicate that an enumeration case is recursive by writing indirect before it, which tells the compiler to insert the necessary layer of indirection.
     1018
     1019For example, here is an enumeration that stores simple arithmetic expressions:
     1020\begin{swift}
     1021enum ArithmeticExpression {
     1022        case number(Int)
     1023        indirect case addition(ArithmeticExpression, ArithmeticExpression)
     1024        indirect case multiplication(ArithmeticExpression, ArithmeticExpression)
     1025}
     1026\end{swift}
     1027You 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:
     1028\begin{swift}
     1029indirect enum ArithmeticExpression {
     1030        case number(Int)
     1031        case addition(ArithmeticExpression, ArithmeticExpression)
     1032        case multiplication(ArithmeticExpression, ArithmeticExpression)
     1033}
     1034\end{swift}
     1035This enumeration can store three kinds of arithmetic expressions: a plain number, the addition of two expressions, and the multiplication of two expressions.
     1036The addition and multiplication cases have associated values that are also arithmetic expressions -- these associated values make it possible to nest expressions.
     1037For 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.
     1038Because the data is nested, the enumeration used to store the data also needs to support nesting -- this means the enumeration needs to be recursive.
     1039The code below shows the ArithmeticExpression recursive enumeration being created for (5 + 4) * 2:
     1040\begin{swift}
     1041let five = ArithmeticExpression.number(5)
     1042let four = ArithmeticExpression.number(4)
     1043let sum = ArithmeticExpression.addition(five, four)
     1044let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2))
     1045\end{swift}
     1046A recursive function is a straightforward way to work with data that has a recursive structure.
     1047For example, here's a function that evaluates an arithmetic expression:
     1048\begin{swift}
     1049func evaluate(_ expression: ArithmeticExpression) -> Int {
     1050        switch expression {
     1051        case let .number(value):
     1052                return value
     1053        case let .addition(left, right):
     1054                return evaluate(left) + evaluate(right)
     1055        case let .multiplication(left, right):
     1056                return evaluate(left) * evaluate(right)
     1057        }
     1058}
     1059
     1060print(evaluate(product))
     1061// Prints "18"
     1062\end{swift}
     1063This function evaluates a plain number by simply returning the associated value.
     1064It 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.
     1065
     1066
     1067\section{Python 3.13}
     1068% https://docs.python.org/3/howto/enum.html
     1069
     1070Python is a dynamically-typed reflexive programming language with multiple versions, and hence, it is possible to extend existing or build new language features within the language.
     1071As a result, discussing Python enumerations is a moving target, because if a features does not exist, it can often be created with varying levels of complexity within the language.
     1072Nevertheless, the following is a discuss of the core enumeration features that come with Python 3.13.
     1073
     1074A Python enumeration type is a set of ordered scoped identifiers (enumerators) bound to \emph{unique} values.
     1075An enumeration is not a basic type;
     1076it is a @class@ inheriting from the @Enum@ class, where the enumerators must be explicitly initialized, \eg:
     1077\begin{python}
     1078class Week(@Enum@): Mon = 1; Tue = 2; Wed = 3; Thu = 4; Fri = 5; Sat = 6; Sun = 7
     1079\end{python}
     1080and/or explicitly auto initialized, \eg:
     1081\begin{python}
     1082class Week(Enum): Mon = 1; Tue = 2; Wed = 3; Thu = 10; Fri = @auto()@; Sat = 4; Sun = @auto()@
     1083\end{python}
     1084where @auto@ increments by 1 from the previous enumerator value \see{Golang \lstinline[language=Go]{iota}, \VRef{s:Golang}}.
     1085Object initialization and assignment are restricted to the enumerators of this type.
     1086An enumerator initialized with same value is an alias and invisible at the enumeration level, \ie the alias it substituted for its aliasee.
     1087\begin{python}
     1088class Week(Enum): Mon = 1; Tue = 2; Wed = 3; Thu = 10; Fri = @10@; Sat = @10@; Sun = @10@
     1089\end{python}
     1090Here, the enumeration has only 4 enumerators and 3 aliases.
     1091An alias is only visible by dropping down to the @class@ level and asking for class members.
     1092@Enum@ only supports equality comparison between enumerator values;
     1093the extended class @OrderedEnum@ adds relational operators @<@, @<=@, @>@, and @>=@.
     1094
     1095There are bidirectional enumeration pseudo-functions for label and value, but there is no concept of access using ordering (position).
    8101096\begin{cquote}
    8111097\setlength{\tabcolsep}{15pt}
    8121098\begin{tabular}{@{}ll@{}}
    813 \begin{swift}
    814 if @week <= .Fri@ {
    815         print( "weekday" );
    816 }
    817 
    818 
    819 \end{swift}
     1099\begin{python}
     1100Week.Thu.value == 10;
     1101Week.Thu.name == 'Thu';
     1102\end{python}
    8201103&
    821 \begin{swift}
    822 switch @week@ {
    823         case .Mon: print( "Mon" )
    824         ...
    825         case .Sun: print( "Sun" )
    826 }
    827 \end{swift}
     1104\begin{python}
     1105Week( 10 ) == Thu
     1106Week['Thu'].value = 10
     1107\end{python}
    8281108\end{tabular}
    8291109\end{cquote}
    8301110
    831 Enumerating is accomplished by inheriting from @CaseIterable@ without any associated values.
    832 \begin{swift}
    833 enum Week: Comparable, @CaseIterable@ {
    834         case Mon, Tue, Wed, Thu, Fri, Sat, Sun // unit-type
    835 };
    836 var weeki : Week = Week.Mon;
    837 if weeki <= .Fri {
    838         print( "weekday" );
    839 }
    840 for day in Week@.allCases@ {
    841         print( day, terminator:" " )
    842 }
    843 weekday
    844 Mon Tue Wed Thu Fri Sat Sun
    845 \end{swift}
    846 The @enum.allCases@ property returns a collection of all the cases for looping over an enumeration type or variable (expensive operation).
    847 
    848 A typed enumeration is accomplished by inheriting from any Swift type, and accessing the underlying enumerator value is done with attribute @rawValue@.
    849 Type @Int@ has auto-incrementing from previous enumerator;
    850 type @String@ has auto-incrementing of the enumerator label.
    851 \begin{cquote}
    852 \setlength{\tabcolsep}{15pt}
    853 \begin{tabular}{@{}lll@{}}
    854 \begin{swift}
    855 enum WeekInt: @Int@, CaseIterable {
    856         case Mon, Tue, Wed, Thu = 10, Fri,
    857                         Sat = 4, Sun // auto-incrementing
    858 };
    859 for day in WeekInt.allCases {
    860         print( day@.rawValue@, terminator:" " )
    861 }
    862 0 1 2 10 11 4 5
    863 \end{swift}
    864 &
    865 \begin{swift}
    866 enum WeekStr: @String@, CaseIterable {
    867         case Mon = "MON", Tue, Wed, Thu, Fri,
    868                         Sat = "SAT", Sun
    869 };
    870 for day in WeekStr.allCases {
    871         print( day@.rawValue@, terminator:" " )
    872 }
    873 MON Tue Wed Thu Fri SAT Sun
    874 \end{swift}
    875 \end{tabular}
    876 \end{cquote}
    877 
    878 There is a bidirectional conversion from typed enumerator to @rawValue@ and vise versa.
    879 \begin{swift}
    880 var weekInt : WeekInt = WeekInt.Mon;
    881 if let opt = WeekInt( rawValue: 0 ) {  // test optional return value
    882         print( weekInt.rawValue, opt )  // 0 Mon
    883 } else {
    884         print( "invalid weekday lookup" )
    885 }
    886 \end{swift}
    887 Conversion from @rawValue@ to enumerator may fail (bad lookup), so the result is an optional value.
    888 
    889 
    890 \section{Python 3.13}
    891 % https://docs.python.org/3/howto/enum.html
    892 
    893 Python is a dynamically-typed reflexive programming language with multiple incompatible versions.
    894 The generality of the language makes it is possible to extend existing or build new language features.
    895 As a result, discussing Python enumerations is a moving target, because if a features does not exist, it can often be created with varying levels of complexity within the language.
    896 Therefore, the following discussion is (mostly) restricted to the core enumeration features in Python 3.13.
    897 
    898 A Python enumeration is not a basic type;
    899 it is a @class@ inheriting from the @Enum@ class.
    900 The @Enum@ class presents a set of scoped enumerators, where each enumerator is a pair object with a \emph{constant} string name and arbitrary value.
    901 Hence, an enumeration instance is a fixed type (enumeration pair), and its value is the type of one of the enumerator pairs.
    902 
    903 The enumerator value fields must be explicitly initialized and be \emph{unique}.
    904 \begin{python}
    905 class Week(!Enum!): Mon = 1; Tue = 2; Wed = 3; Thu = 4; Fri = 5; Sat = 6; Sun = 7
    906 \end{python}
    907 and/or explicitly auto initialized, \eg:
    908 \begin{python}
    909 class Week(Enum): Mon = 1; Tue = 2; Wed = 3; Thu = 10; Fri = !auto()!; Sat = 4; Sun = !auto()!
    910 Mon : 1 Tue : 2 Wed : 3 Thu : 10 Fri : !11! Sat : 4 Sun : !12!
    911 \end{python}
    912 where @auto@ increments by 1 from the previous @auto@ value \see{Golang \lstinline[language=Go]{iota}, \VRef{s:Golang}}.
    913 @auto@ is controlled by member @_generate_next_value_()@, which can be overridden:
    914 \begin{python}
    915 @staticmethod
    916 def _generate_next_value_( name, start, count, last_values ):
    917         return name
    918 \end{python}
    919 
    920 There is no direct concept of restricting the enumerators in an enumeration \emph{instance} because the dynamic typing changes the type.
    921 \begin{python}
    922 class RGB(Enum): Red = 1; Green = 2; Blue = 3
    923 day : Week = Week.Tue;          $\C{\# type is Week}$
    924 !day = RGB.Red!                         $\C{\# type is RGB}$
    925 !day : Week = RGB.Red!          $\C{\# type is RGB}$
    926 \end{python}
    927 The enumerators are constants and cannot be reassigned.
    928 Hence, while enumerators can be different types,
    929 \begin{python}
    930 class Diff(Enum): Int = 1; Float = 3.5; Str = "ABC"
    931 \end{python}
    932 it is not an ADT because the enumerator names are not constructors.
    933 
    934 An enumerator initialized with the same value is an alias and invisible at the enumeration level, \ie the alias is substituted for its aliasee.
    935 \begin{python}
    936 class WeekD(Enum): Mon = 1; Tue = 2; Wed = 3; Thu = !10!; Fri = !10!; Sat = !10!; Sun = !10!
    937 \end{python}
    938 Here, the enumeration has only 4 enumerators and 3 aliases.
    939 An alias is only visible by dropping down to the @class@ level and asking for class members.
    940 Aliasing is prevented using the @unique@ decorator.
    941 \begin{python}
    942 !@unique!
    943 class DupVal(Enum): One = 1; Two = 2; Three = !3!; Four = !3!
    944 ValueError: duplicate values found in <enum 'DupVal'>: Four -> Three
    945 \end{python}
    946 
    947 \begin{lrbox}{\myboxA}
    948 \begin{python}
    949 def by_position(enum_type, position):
    950         for index, value in enumerate(enum_type):
    951                 if position == index: return value
    952         raise Exception("by_position out of range")
    953 \end{python}
    954 \end{lrbox}
    955 There are bidirectional enumeration pseudo-functions for label and value, but there is no concept of access using ordering (position).\footnote{
    956 There is an $O(N)$ mechanism to access an enumerator's value by position. \newline \usebox\myboxA}
    957 \begin{cquote}
    958 \setlength{\tabcolsep}{15pt}
    959 \begin{tabular}{@{}ll@{}}
    960 \begin{python}
    961 Week.Thu.value == 4;
    962 Week.Thu.name == "Thu";
    963 \end{python}
    964 &
    965 \begin{python}
    966 Week( 4 ) == Week.Thu
    967 Week["Thu"].value == 4
    968 \end{python}
    969 \end{tabular}
    970 \end{cquote}
    971 @Enum@ only supports equality comparison between enumerator values.
    972 There are multiple library extensions to @Enum@, \eg @OrderedEnum@ recipe class, adding relational operators @<@, @<=@, @>@, and @>=@.
    973 
    9741111An enumeration \lstinline[language=python]{class} can have methods.
    9751112\begin{python}
    976 class Week(!OrderedEnum!):
     1113class Week(Enum):
    9771114        Mon = 1; Tue = 2; Wed = 3; Thu = 4; Fri = 5; Sat = 6; Sun = 7
    978         def !isWeekday(self)!:          # method
    979                 return Week(self.value) !<=! Week.Fri
    980         def !isWeekend(self)!:          # method
    981                 return Week.Sat !<=! Week(self.value)
    982 \end{python}
    983 
    984 An enumeration can be used in the @if@ and @switch@ statements but only for equality tests, unless extended to @OrderedEnum@.
    985 \begin{cquote}
    986 \setlength{\tabcolsep}{12pt}
    987 \begin{tabular}{@{}ll@{}}
    988 \begin{python}
    989 if day <= Week.Fri :
    990         print( "weekday" );
    991 
    992 
    993 
    994 \end{python}
    995 &
    996 \begin{python}
    997 match day:
    998         case Week.Mon | Week.Tue | Week.Wed | Week.Thu | Week.Fri:
    999                 print( "weekday" );
    1000         case Week.Sat | Week.Sun:
    1001                 print( "weekend" );
    1002 \end{python}
    1003 \end{tabular}
    1004 \end{cquote}
    1005 Looping is performed using the enumeration type or @islice@ from @itertools@ based on position.
    1006 \begin{python}
    1007 for day in !Week!:                                      $\C[2.25in]{\# Mon : 1 Tue : 2 Wed : 3 Thu : 4 Fri : 5 Sat : 6 Sun : 7}$
    1008         print( day.name, ":", day.value, end=" " )
    1009 for day in !islice(Week, 0, 5)!:        $\C{\# Mon : 1 Tue : 2 Wed : 3 Thu : 4 Fri : 5}$
    1010         print( day.name, ":", day.value, end=" " )
    1011 for day in !islice(Week, 5, 7)!:        $\C{\# Sat : 6 Sun : 7}$
    1012         print( day.name, ":", day.value, end=" " )
    1013 for day in !islice(Week,0, 7, 2)!:      $\C{\# Mon : 1 Wed : 3 Fri : 5 Sun : 7}\CRT$
    1014         print( day.name, ":", day.value, end=" " )
    1015 \end{python}
    1016 Iterating that includes alias names only (strings) is done using attribute @__members__@.
    1017 \begin{python}
    1018 for day in WeekD.__members__:
    1019         print( day, ":", end=" " )
    1020 Mon : Tue : Wed : Thu : Fri : Sat : Sun
    1021 \end{python}
    1022 
    1023 Enumeration subclassing is allowed only if the enumeration base-class does not define any members.
    1024 \begin{python}
    1025 class WeekE(OrderedEnum): !pass!;  # no members
    1026 class WeekDay(WeekE): Mon = 1; Tue = 2; Wed = 3; Thu = 4; Fri = 5;
    1027 class WeekEnd(WeekE): Sat = 6; Sun = 7
    1028 \end{python}
    1029 Here, type @WeekE@ is an abstract type because the dynamic typing never uses it.
    1030 \begin{cquote}
    1031 \setlength{\tabcolsep}{25pt}
    1032 \begin{tabular}{@{}ll@{}}
    1033 \begin{python}
    1034 print( type(WeekE) )
    1035 day : WeekE = WeekDay.Fri       # set type
    1036 print( type(day), day )
    1037 day = WeekEnd.Sat                           # set type
    1038 print( type(day), day )
    1039 \end{python}
    1040 &
    1041 \begin{python}
    1042 <$class$ 'enum.EnumType'>
    1043 
    1044 <enum 'WeekDay'> WeekDay.Fri
    1045 
    1046 <enum 'WeekEnd'> WeekEnd.Sat
    1047 \end{python}
    1048 \end{tabular}
    1049 \end{cquote}
    1050 
    1051 There are a number of supplied enumeration base-types: @IntEnum@, @StrEnum@, @IntFalg@, @Flag@, which restrict the values in an enum using multi-inheritance.
    1052 @IntEnum@ is a subclass of @int@ and @Enum@, allowing enumerator comparison to @int@ and other enumerators of this type (like C enumerators).
    1053 @StrEnum@ is the same as @IntEnum@ but a subclass of the string type \lstinline[language=python]{str}.
    1054 @IntFlag@, is a restricted subclass of @int@ where the enumerators can be combined using the bitwise operators (@&@, @|@, @^@, @~@) and the result is an @IntFlag@ member.
    1055 @Flag@ is the same as @IntFlag@ but cannot be combined with, nor compared against, any other @Flag@ enumeration, nor @int@.
    1056 Auto increment for @IntFlag@ and @Flag@ is by powers of 2.
    1057 Enumerators that are a combinations of single bit enumerators are aliases, and hence, invisible.
    1058 The following is an example for @Flag@.
    1059 \begin{python}
    1060 class WeekF(Flag): Mon = 1; Tue = 2; Wed = 4; Thu = !auto()!; Fri = 16; Sat = 32; Sun = 64; \
    1061           Weekday = Mon | Tue | Wed | Thu | Fri; \
    1062           Weekend = Sat | Sun
    1063 print( f"0x{repr(WeekF.Weekday.value)} 0x{repr(WeekF.Weekend.value)}" )
    1064 0x31 0x96
    1065 \end{python}
    1066 It is possible to enumerate through a @Flag@ enumerator (no aliases):
    1067 \begin{python}
    1068 for day in WeekF:
    1069         print( f"{day.name}: {day.value}", end=" ")
    1070 Mon: 1 Tue: 2 Wed: 4 Thu: 8 Fri: 16 Sat: 32 Sun: 64
    1071 \end{python}
    1072 and a combined alias enumerator for @Flag@.
    1073 \begin{cquote}
    1074 \setlength{\tabcolsep}{15pt}
    1075 \begin{tabular}{@{}ll@{}}
    1076 \begin{python}
    1077 weekday = WeekF.Weekday
    1078 for day in weekday:
    1079         print( f"{day.name}:"
    1080                    f" {day.value}", end=" " )
    1081 Mon: 1 Tue: 2 Wed: 4 Thu: 8 Fri: 16
    1082 \end{python}
    1083 &
    1084 \begin{python}
    1085 weekend = WeekF.Weekend
     1115        $\\@$classmethod
     1116        def today(cls, date):
     1117                return cls(date.isoweekday())
     1118print( "today:", Week.today(date.today()))
     1119today: Week.Mon
     1120\end{python}
     1121The method @today@ retrieves the day of the week and uses it as an index to print out the corresponding label of @Week@.
     1122
     1123@Flag@ allows combining several members into a single variable:
     1124\begin{python}
     1125print( repr(WeekF.Sat | WeekF.Sun) )
     1126<WeekF.Sun|Sat: 96>
     1127\end{python}
     1128You can even iterate over a @Flag@ variable:
     1129\begin{python}
    10861130for day in weekend:
    1087         print( f"{day.name}:"
    1088                    f" {day.value}", end=" " )
    1089 Sat: 32 Sun: 64
    1090 \end{python}
    1091 \end{tabular}
    1092 \end{cquote}
     1131        print(day)
     1132WeekF.Sat
     1133WeekF.Sun
     1134\end{python}
     1135Okay, let's get some chores set up:
     1136\begin{python}
     1137>>> chores_for_ethan = {
     1138...    'feed the cat': Week.MONDAY | Week.WEDNESDAY | Week.FRIDAY,
     1139...    'do the dishes': Week.TUESDAY | Week.THURSDAY,
     1140...    'answer SO questions': Week.SATURDAY,
     1141...    }
     1142\end{python}
     1143And a function to display the chores for a given day:
     1144\begin{python}
     1145>>> def show_chores(chores, day):
     1146...    for chore, days in chores.items():
     1147...        if day in days:
     1148...            print(chore)
     1149>>> show_chores(chores_for_ethan, Week.SATURDAY)
     1150answer SO questions
     1151\end{python}
     1152Auto incrmenet for @Flag@ is by powers of 2.
     1153\begin{python}
     1154class WeekF(Flag): Mon = auto(); Tue = auto(); Wed = auto(); Thu = auto(); Fri = auto();  \
     1155                                                        Sat = auto(); Sun = auto(); Weekend = Sat | Sun
     1156for d in WeekF:
     1157        print( f"{d.name}: {d.value}", end=" ")
     1158Mon: 1 Tue: 2 Wed: 4 Thu: 8 Fri: 16 Sat: 32 Sun: 64 WeekA.Weekend
     1159\end{python}
     1160
     1161\subsection{Programmatic access to enumeration members and their attributes}
     1162
     1163Sometimes it's useful to access members in enumerations programmatically (i.e. situations where @Color.RED@ won't do because the exact color is not known at program-writing time).
     1164@Enum@ allows such access:
     1165\begin{python}
     1166print(RGB(1), RGB(3), )
     1167RGB.RED RGB.GREEN
     1168\end{python}
     1169If you want to access enum members by name, use item access:
     1170\begin{python}
     1171print( RGBa['RED'], RGBa['GREEN'] )
     1172RGB.RED RGB.GREEN
     1173\end{python}
     1174If you have an enum member and need its name or value:
     1175\begin{python}
     1176member = RGBa.RED
     1177print( f"{member.name} {member.value}" )
     1178RED 1
     1179\end{python}
     1180
     1181
     1182\subsection{Ensuring unique enumeration values}
     1183
     1184By default, enumerations allow multiple names as aliases for the same value.
     1185When this behavior isn't desired, you can use the @unique()@ decorator:
     1186\begin{python}
     1187from enum import Enum, unique
     1188$@$unique
     1189class DupVal(Enum): ONE = 1; TWO = 2; THREE = 3; FOUR = 3
     1190ValueError: duplicate values found in <enum 'Mistake'>: FOUR -> THREE
     1191\end{python}
     1192
     1193\subsection{Using automatic values}
     1194
     1195If the exact value is unimportant you can use @auto@:
     1196\begin{python}
     1197from enum import Enum, auto
     1198class RGBa(Enum): RED = auto(); BLUE = auto(); GREEN = auto()
     1199\end{python}
     1200(Like Golang @iota@.)
     1201The values are chosen by @_generate_next_value_()@, which can be overridden:
     1202\begin{python}
     1203>>> class AutoName(Enum):
     1204...     $@$staticmethod
     1205...     def _generate_next_value_(name, start, count, last_values):
     1206...         return name
     1207...
     1208>>> class Ordinal(AutoName):
     1209...     NORTH = auto()
     1210...     SOUTH = auto()
     1211...     EAST = auto()
     1212...     WEST = auto()
     1213...
     1214>>> [member.value for member in Ordinal]
     1215['NORTH', 'SOUTH', 'EAST', 'WEST']
     1216\end{python}
     1217Note The @_generate_next_value_()@ method must be defined before any members.
     1218
     1219\subsection{Iteration}
     1220
     1221Iterating over the members of an enum does not provide the aliases:
     1222\begin{python}
     1223>>> list(Shape)
     1224[<Shape.SQUARE: 2>, <Shape.DIAMOND: 1>, <Shape.CIRCLE: 3>]
     1225>>> list(Week)
     1226[<Week.MONDAY: 1>, <Week.TUESDAY: 2>, <Week.WEDNESDAY: 4>, <Week.THURSDAY: 8>,
     1227<Week.FRIDAY: 16>, <Week.SATURDAY: 32>, <Week.SUNDAY: 64>]
     1228\end{python}
     1229Note that the aliases @Shape.ALIAS_FOR_SQUARE@ and @Week.WEEKEND@ aren't shown.
     1230
     1231The special attribute @__members__@ is a read-only ordered mapping of names to members.
     1232It includes all names defined in the enumeration, including the aliases:
     1233\begin{python}
     1234>>> for name, member in Shape.__members__.items():
     1235...     name, member
     1236...
     1237('SQUARE', <Shape.SQUARE: 2>)
     1238('DIAMOND', <Shape.DIAMOND: 1>)
     1239('CIRCLE', <Shape.CIRCLE: 3>)
     1240('ALIAS_FOR_SQUARE', <Shape.SQUARE: 2>)
     1241\end{python}
     1242The @__members__@ attribute can be used for detailed programmatic access to the enumeration members.
     1243For example, finding all the aliases:
     1244\begin{python}
     1245>>> [name for name, member in Shape.__members__.items() if member.name != name]
     1246['ALIAS_FOR_SQUARE']
     1247\end{python}
     1248Note: Aliases for flags include values with multiple flags set, such as 3, and no flags set, i.e. 0.
     1249
     1250\subsection{Comparisons}
     1251
     1252Enumeration members are compared by identity:
     1253\begin{python}
     1254>>> Color.RED is Color.RED
     1255True
     1256>>> Color.RED is Color.BLUE
     1257False
     1258>>> Color.RED is not Color.BLUE
     1259True
     1260\end{python}
     1261Ordered comparisons between enumeration values are not supported.
     1262Enum members are not integers (but see @IntEnum@ below):
     1263\begin{python}
     1264>>> Color.RED < Color.BLUE
     1265Traceback (most recent call last):
     1266  File "<stdin>", line 1, in <module>
     1267TypeError: '<' not supported between instances of 'Color' and 'Color'
     1268\end{python}
     1269Equality comparisons are defined though:
     1270\begin{python}
     1271>>> Color.BLUE == Color.RED
     1272False
     1273>>> Color.BLUE != Color.RED
     1274True
     1275>>> Color.BLUE == Color.BLUE
     1276True
     1277\end{python}
     1278Comparisons against non-enumeration values will always compare not equal (again, @IntEnum@ was explicitly designed to behave differently, see below):
     1279\begin{python}
     1280>>> Color.BLUE == 2
     1281False
     1282\end{python}
     1283
     1284Warning: It is possible to reload modules -- if a reloaded module contains enums, they will be recreated, and the new members may not compare identical/equal to the original members.
     1285
     1286\subsection{Allowed members and attributes of enumerations}
     1287
     1288Most of the examples above use integers for enumeration values.
     1289Using integers is short and handy (and provided by default by the Functional API), but not strictly enforced.
     1290In the vast majority of use-cases, one doesn't care what the actual value of an enumeration is.
     1291But if the value is important, enumerations can have arbitrary values.
     1292
     1293Enumerations are Python classes, and can have methods and special methods as usual. If we have this enumeration:
     1294\begin{python}
     1295>>> class Mood(Enum):
     1296...     FUNKY = 1
     1297...     HAPPY = 3
     1298...
     1299...     def describe(self):
     1300...         # self is the member here
     1301...         return self.name, self.value
     1302...
     1303...     def __str__(self):
     1304...         return 'my custom str! {0}'.format(self.value)
     1305...
     1306...     $@$classmethod
     1307...
     1308...     def favorite_mood(cls):
     1309...         # cls here is the enumeration
     1310...         return cls.HAPPY
     1311...
     1312\end{python}
     1313Then:
     1314\begin{python}
     1315>>> Mood.favorite_mood()
     1316<Mood.HAPPY: 3>
     1317>>> Mood.HAPPY.describe()
     1318('HAPPY', 3)
     1319>>> str(Mood.FUNKY)
     1320'my custom str! 1'
     1321\end{python}
     1322The rules for what is allowed are as follows: names that start and end with a single underscore are reserved by enum and cannot be used;
     1323all other attributes defined within an enumeration will become members of this enumeration, with the exception of special methods (@__str__()@, @__add__()@, etc.), descriptors (methods are also descriptors), and variable names listed in @_ignore_@.
     1324
     1325Note: if your enumeration defines @__new__()@ and/or @__init__()@, any value(s) given to the enum member will be passed into those methods.
     1326See Planet for an example.
     1327
     1328Note: The @__new__()@ method, if defined, is used during creation of the Enum members;
     1329it is then replaced by Enum's @__new__()@ which is used after class creation for lookup of existing members.
     1330See When to use @__new__()@ vs. @__init__()@ for more details.
     1331
     1332\subsection{Restricted Enum subclassing}
     1333
     1334A new @Enum@ class must have one base enum class, up to one concrete data type, and as many object-based mixin classes as needed.
     1335The order of these base classes is:
     1336\begin{python}
     1337class EnumName([mix-in, ...,] [data-type,] base-enum):
     1338        pass
     1339\end{python}
     1340Also, subclassing an enumeration is allowed only if the enumeration does not define any members.
     1341So this is forbidden:
     1342\begin{python}
     1343>>> class MoreColor(Color):
     1344...     PINK = 17
     1345...
     1346Traceback (most recent call last):
     1347...
     1348TypeError: <enum 'MoreColor'> cannot extend <enum 'Color'>
     1349\end{python}
     1350But this is allowed:
     1351\begin{python}
     1352>>> class Foo(Enum):
     1353...     def some_behavior(self):
     1354...         pass
     1355...
     1356>>> class Bar(Foo):
     1357...     HAPPY = 1
     1358...     SAD = 2
     1359...
     1360\end{python}
     1361Allowing subclassing of enums that define members would lead to a violation of some important invariants of types and instances.
     1362On the other hand, it makes sense to allow sharing some common behavior between a group of enumerations. (See OrderedEnum for an example.)
     1363
     1364\subsection{Dataclass support}
     1365
     1366When inheriting from a @dataclass@, the @__repr__()@ omits the inherited class' name.
     1367For example:
     1368\begin{python}
     1369>>> from dataclasses import dataclass, field
     1370>>> $@$dataclass
     1371... class CreatureDataMixin:
     1372...     size: str
     1373...     legs: int
     1374...     tail: bool = field(repr=False, default=True)
     1375...
     1376>>> class Creature(CreatureDataMixin, Enum):
     1377...     BEETLE = 'small', 6
     1378...     DOG = 'medium', 4
     1379...
     1380>>> Creature.DOG
     1381<Creature.DOG: size='medium', legs=4>
     1382\end{python}
     1383Use the @dataclass()@ argument repr=False to use the standard @repr()@.
     1384
     1385Changed in version 3.12: Only the dataclass fields are shown in the value area, not the dataclass' name.
     1386
     1387\subsection{Pickling}
     1388
     1389Enumerations can be pickled and unpickled:
     1390\begin{python}
     1391>>> from test.test_enum import Fruit
     1392>>> from pickle import dumps, loads
     1393>>> Fruit.TOMATO is loads(dumps(Fruit.TOMATO))
     1394True
     1395\end{python}
     1396The usual restrictions for pickling apply: picklable enums must be defined in the top level of a module, since unpickling requires them to be importable from that module.
     1397
     1398Note: With pickle protocol version 4 it is possible to easily pickle enums nested in other classes.
     1399
     1400It is possible to modify how enum members are pickled/unpickled by defining @__reduce_ex__()@ in the enumeration class.
     1401The default method is by-value, but enums with complicated values may want to use by-name:
     1402\begin{python}
     1403>>> import enum
     1404>>> class MyEnum(enum.Enum):
     1405...     __reduce_ex__ = enum.pickle_by_enum_name
     1406\end{python}
     1407Note: Using by-name for flags is not recommended, as unnamed aliases will not unpickle.
     1408
     1409\subsection{Functional API}
     1410
     1411The @Enum@ class is callable, providing the following functional API:
     1412\begin{python}
     1413>>> Animal = Enum('Animal', 'ANT BEE CAT DOG')
     1414>>> Animal
     1415<enum 'Animal'>
     1416>>> Animal.ANT
     1417<Animal.ANT: 1>
     1418>>> list(Animal)
     1419[<Animal.ANT: 1>, <Animal.BEE: 2>, <Animal.CAT: 3>, <Animal.DOG: 4>]
     1420\end{python}
     1421The semantics of this API resemble @namedtuple@.
     1422The first argument of the call to @Enum@ is the name of the enumeration.
     1423
     1424The second argument is the source of enumeration member names.
     1425It can be a whitespace-separated string of names, a sequence of names, a sequence of 2-tuples with key/value pairs, or a mapping (e.g. dictionary) of names to values.
     1426The last two options enable assigning arbitrary values to enumerations;
     1427the others auto-assign increasing integers starting with 1 (use the @start@ parameter to specify a different starting value).
     1428A new class derived from @Enum@ is returned.
     1429In other words, the above assignment to Animal is equivalent to:
     1430\begin{python}
     1431>>> class Animal(Enum):
     1432...     ANT = 1
     1433...     BEE = 2
     1434...     CAT = 3
     1435...     DOG = 4
     1436...
     1437\end{python}
     1438The reason for defaulting to 1 as the starting number and not 0 is that 0 is @False@ in a boolean sense, but by default enum members all evaluate to @True@.
     1439
     1440Pickling enums created with the functional API can be tricky as frame stack implementation details are used to try and figure out which module the enumeration is being created in (e.g. it will fail if you use a utility function in a separate module, and also may not work on IronPython or Jython).
     1441The solution is to specify the module name explicitly as follows:
     1442\begin{python}
     1443>>> Animal = Enum('Animal', 'ANT BEE CAT DOG', module=__name__)
     1444\end{python}
     1445Warning: If module is not supplied, and @Enum@ cannot determine what it is, the new @Enum@ members will not be unpicklable; to keep errors closer to the source, pickling will be disabled.
     1446
     1447The new pickle protocol 4 also, in some circumstances, relies on @__qualname__@ being set to the location where pickle will be able to find the class.
     1448For example, if the class was made available in class SomeData in the global scope:
     1449\begin{python}
     1450>>> Animal = Enum('Animal', 'ANT BEE CAT DOG', qualname='SomeData.Animal')
     1451\end{python}
     1452The complete signature is:
     1453\begin{python}
     1454Enum(
     1455        value='NewEnumName',
     1456        names=<...>,
     1457        *,
     1458        module='...',
     1459        qualname='...',
     1460        type=<mixed-in class>,
     1461        start=1,
     1462        )
     1463\end{python}
     1464\begin{itemize}
     1465\item
     1466@value@: What the new enum class will record as its name.
     1467\item
     1468@names@: The enum members.
     1469This can be a whitespace- or comma-separated string (values will start at 1 unless otherwise specified):
     1470\begin{python}
     1471'RED GREEN BLUE' | 'RED,GREEN,BLUE' | 'RED, GREEN, BLUE'
     1472\end{python}
     1473or an iterator of names:
     1474\begin{python}
     1475['RED', 'GREEN', 'BLUE']
     1476\end{python}
     1477or an iterator of (name, value) pairs:
     1478\begin{python}
     1479[('CYAN', 4), ('MAGENTA', 5), ('YELLOW', 6)]
     1480\end{python}
     1481or a mapping:
     1482\begin{python}
     1483{'CHARTREUSE': 7, 'SEA_GREEN': 11, 'ROSEMARY': 42}
     1484\end{python}
     1485\item
     1486module: name of module where new enum class can be found.
     1487\item
     1488@qualname@: where in module new enum class can be found.
     1489\item
     1490@type@: type to mix in to new enum class.
     1491\item
     1492@start@: number to start counting at if only names are passed in.
     1493\end{itemize}
     1494Changed in version 3.5: The start parameter was added.
     1495
     1496\subsection{Derived Enumerations}
     1497
     1498\subsection{IntEnum}
     1499
     1500The first variation of @Enum@ that is provided is also a subclass of @int@.
     1501Members of an @IntEnum@ can be compared to integers;
     1502by extension, integer enumerations of different types can also be compared to each other:
     1503\begin{python}
     1504>>> from enum import IntEnum
     1505>>> class Shape(IntEnum):
     1506...     CIRCLE = 1
     1507...     SQUARE = 2
     1508...
     1509>>> class Request(IntEnum):
     1510...     POST = 1
     1511...     GET = 2
     1512...
     1513>>> Shape == 1
     1514False
     1515>>> Shape.CIRCLE == 1
     1516True
     1517>>> Shape.CIRCLE == Request.POST
     1518True
     1519\end{python}
     1520However, they still can't be compared to standard @Enum@ enumerations:
     1521\begin{python}
     1522>>> class Shape(IntEnum):
     1523...     CIRCLE = 1
     1524...     SQUARE = 2
     1525...
     1526>>> class Color(Enum):
     1527...     RED = 1
     1528...     GREEN = 2
     1529...
     1530>>> Shape.CIRCLE == Color.RED
     1531False
     1532\end{python}
     1533@IntEnum@ values behave like integers in other ways you'd expect:
     1534\begin{python}
     1535>>> int(Shape.CIRCLE)
     15361
     1537>>> ['a', 'b', 'c'][Shape.CIRCLE]
     1538'b'
     1539>>> [i for i in range(Shape.SQUARE)]
     1540[0, 1]
     1541\end{python}
     1542
     1543\subsection{StrEnum}
     1544
     1545The second variation of @Enum@ that is provided is also a subclass of @str@.
     1546Members of a @StrEnum@ can be compared to strings;
     1547by extension, string enumerations of different types can also be compared to each other.
     1548
     1549New in version 3.11.
     1550
     1551\subsection{IntFlag}
     1552
     1553The next variation of @Enum@ provided, @IntFlag@, is also based on @int@.
     1554The difference being @IntFlag@ members can be combined using the bitwise operators (@&, |, ^, ~@) and the result is still an @IntFlag@ member, if possible.
     1555Like @IntEnum@, @IntFlag@ members are also integers and can be used wherever an int is used.
     1556
     1557Note: Any operation on an IntFlag member besides the bit-wise operations will lose the @IntFlag@ membership.
     1558
     1559Bit-wise operations that result in invalid @IntFlag@ values will lose the @IntFlag@ membership.
     1560See @FlagBoundary@ for details.
     1561
     1562New in version 3.6.
     1563
     1564Changed in version 3.11.
     1565
     1566Sample @IntFlag@ class:
     1567\begin{python}
     1568>>> from enum import IntFlag
     1569>>> class Perm(IntFlag):
     1570...     R = 4
     1571...     W = 2
     1572...     X = 1
     1573...
     1574>>> Perm.R | Perm.W
     1575<Perm.R|W: 6>
     1576>>> Perm.R + Perm.W
     15776
     1578>>> RW = Perm.R | Perm.W
     1579>>> Perm.R in RW
     1580True
     1581\end{python}
     1582It is also possible to name the combinations:
     1583\begin{python}
     1584>>> class Perm(IntFlag):
     1585...     R = 4
     1586...     W = 2
     1587...     X = 1
     1588...     RWX = 7
     1589...
     1590>>> Perm.RWX
     1591<Perm.RWX: 7>
     1592>>> ~Perm.RWX
     1593<Perm: 0>
     1594>>> Perm(7)
     1595<Perm.RWX: 7>
     1596\end{python}
     1597Note: Named combinations are considered aliases. Aliases do not show up during iteration, but can be returned from by-value lookups.
     1598
     1599Changed in version 3.11.
     1600
     1601Another important difference between @IntFlag@ and @Enum@ is that if no flags are set (the value is 0), its boolean evaluation is @False@:
     1602\begin{python}
     1603>>> Perm.R & Perm.X
     1604<Perm: 0>
     1605>>> bool(Perm.R & Perm.X)
     1606False
     1607\end{python}
     1608Because @IntFlag@ members are also subclasses of int they can be combined with them (but may lose @IntFlag@ membership:
     1609\begin{python}
     1610>>> Perm.X | 4
     1611<Perm.R|X: 5>
     1612
     1613>>> Perm.X + 8
     16149
     1615\end{python}
     1616Note: The negation operator, @~@, always returns an @IntFlag@ member with a positive value:
     1617\begin{python}
     1618>>> (~Perm.X).value == (Perm.R|Perm.W).value == 6
     1619True
     1620\end{python}
     1621@IntFlag@ members can also be iterated over:
     1622\begin{python}
     1623>>> list(RW)
     1624[<Perm.R: 4>, <Perm.W: 2>]
     1625\end{python}
     1626New in version 3.11.
     1627
     1628\subsection{Flag}
     1629
     1630The last variation is @Flag@.
     1631Like @IntFlag@, @Flag@ members can be combined using the bitwise operators (@&, |, ^, ~@).
     1632Unlike @IntFlag@, they cannot be combined with, nor compared against, any other @Flag@ enumeration, nor @int@.
     1633While it is possible to specify the values directly it is recommended to use @auto@ as the value and let @Flag@ select an appropriate value.
     1634
     1635New in version 3.6.
     1636
     1637Like @IntFlag@, if a combination of @Flag@ members results in no flags being set, the boolean evaluation is @False@:
     1638\begin{python}
     1639>>> from enum import Flag, auto
     1640>>> class Color(Flag):
     1641...     RED = auto()
     1642...     BLUE = auto()
     1643...     GREEN = auto()
     1644...
     1645>>> Color.RED & Color.GREEN
     1646<Color: 0>
     1647>>> bool(Color.RED & Color.GREEN)
     1648False
     1649\end{python}
     1650Individual flags should have values that are powers of two (1, 2, 4, 8, ...), while combinations of flags will not:
     1651\begin{python}
     1652>>> class Color(Flag):
     1653...     RED = auto()
     1654...     BLUE = auto()
     1655...     GREEN = auto()
     1656...     WHITE = RED | BLUE | GREEN
     1657...
     1658>>> Color.WHITE
     1659<Color.WHITE: 7>
     1660\end{python}
     1661Giving a name to the ``no flags set'' condition does not change its boolean value:
     1662\begin{python}
     1663>>> class Color(Flag):
     1664...     BLACK = 0
     1665...     RED = auto()
     1666...     BLUE = auto()
     1667...     GREEN = auto()
     1668...
     1669>>> Color.BLACK
     1670<Color.BLACK: 0>
     1671>>> bool(Color.BLACK)
     1672False
     1673\end{python}
     1674@Flag@ members can also be iterated over:
     1675\begin{python}
     1676>>> purple = Color.RED | Color.BLUE
     1677>>> list(purple)
     1678[<Color.RED: 1>, <Color.BLUE: 2>]
     1679\end{python}
     1680New in version 3.11.
     1681
     1682Note: For the majority of new code, @Enum@ and @Flag@ are strongly recommended, since @IntEnum@ and @IntFlag@ break some semantic promises of an enumeration (by being comparable to integers, and thus by transitivity to other unrelated enumerations).
     1683@IntEnum@ and @IntFlag@ should be used only in cases where @Enum@ and @Flag@ will not do;
     1684for example, when integer constants are replaced with enumerations, or for interoperability with other systems.
     1685
     1686\subsection{Others}
     1687
     1688While @IntEnum@ is part of the enum module, it would be very simple to implement independently:
     1689\begin{python}
     1690class IntEnum(int, Enum):
     1691        pass
     1692\end{python}
     1693This demonstrates how similar derived enumerations can be defined;
     1694for example a @FloatEnum@ that mixes in float instead of @int@.
     1695
     1696Some rules:
     1697\begin{itemize}
     1698\item
     1699When subclassing @Enum@, mix-in types must appear before @Enum@ itself in the sequence of bases, as in the @IntEnum@ example above.
     1700\item
     1701Mix-in types must be subclassable.
     1702For example, @bool@ and @range@ are not subclassable and will throw an error during Enum creation if used as the mix-in type.
     1703\item
     1704While @Enum@ can have members of any type, once you mix in an additional type, all the members must have values of that type, e.g. @int@ above.
     1705This restriction does not apply to mix-ins which only add methods and don't specify another type.
     1706\item
     1707When another data type is mixed in, the value attribute is not the same as the enum member itself, although it is equivalent and will compare equal.
     1708\item
     1709A data type is a mixin that defines @__new__()@, or a @dataclass@
     1710\item
     1711\%-style formatting: @%s@ and @%r@ call the @Enum@ class's @__str__()@ and @__repr__()@ respectively; other codes (such as @%i@ or @%h@ for @IntEnum@) treat the enum member as its mixed-in type.
     1712\item
     1713Formatted string literals, @str.format()@, and format() will use the enum's @__str__()@ method.
     1714\end{itemize}
     1715Note: Because @IntEnum@, @IntFlag@, and @StrEnum@ are designed to be drop-in replacements for existing constants, their @__str__()@ method has been reset to their data types' @__str__()@ method.
     1716
     1717\subsection{When to use \lstinline{__new__()} vs. \lstinline{__init__()}}
     1718
     1719@__new__()@ must be used whenever you want to customize the actual value of the @Enum@ member.
     1720Any other modifications may go in either @__new__()@ or @__init__()@, with @__init__()@ being preferred.
     1721
     1722For example, if you want to pass several items to the constructor, but only want one of them to be the value:
     1723\begin{python}
     1724>>> class Coordinate(bytes, Enum):
     1725...     """
     1726...     Coordinate with binary codes that can be indexed by the int code.
     1727...     """
     1728...     def __new__(cls, value, label, unit):
     1729...         obj = bytes.__new__(cls, [value])
     1730...         obj._value_ = value
     1731...         obj.label = label
     1732...         obj.unit = unit
     1733...         return obj
     1734...     PX = (0, 'P.X', 'km')
     1735...     PY = (1, 'P.Y', 'km')
     1736...     VX = (2, 'V.X', 'km/s')
     1737...     VY = (3, 'V.Y', 'km/s')
     1738
     1739>>> print(Coordinate['PY'])
     1740Coordinate.PY
     1741
     1742>>> print(Coordinate(3))
     1743Coordinate.VY
     1744\end{python}
     1745Warning: Do not call @super().__new__()@, as the lookup-only @__new__@ is the one that is found; instead, use the data type directly.
     1746
     1747\subsection{Finer Points}
     1748
     1749Supported @__dunder__@ names
     1750
     1751@__members__@ is a read-only ordered mapping of member\_name:member items. It is only available on the class.
     1752
     1753@__new__()@, if specified, must create and return the enum members; it is also a very good idea to set the member's @_value_@ appropriately. Once all the members are created it is no longer used.
     1754Supported @_sunder_@ names
     1755\begin{itemize}
     1756\item
     1757@_name_@ -- name of the member
     1758\item
     1759@_value_@ -- value of the member; can be set / modified in @__new__@
     1760\item
     1761@_missing_@ -- a lookup function used when a value is not found; may be overridden
     1762\item
     1763@_ignore_@ -- a list of names, either as a @list@ or a @str@, that will not be transformed into members, and will be removed from the final class
     1764\item
     1765@_order_@ -- used in Python 2/3 code to ensure member order is consistent (class attribute, removed during class creation)
     1766\item
     1767@_generate_@next@_value_@ -- used by the Functional API and by @auto@ to get an appropriate value for an enum member; may be overridden
     1768\end{itemize}
     1769Note: For standard @Enum@ classes the next value chosen is the last value seen incremented by one.
     1770
     1771For @Flag@ classes the next value chosen will be the next highest power-of-two, regardless of the last value seen.
     1772
     1773New in version 3.6: @_missing_@, @_order_@, @_generate_@next@_value_@
     1774
     1775New in version 3.7: @_ignore_@
     1776
     1777To help keep Python 2 / Python 3 code in sync an @_order_@ attribute can be provided.
     1778It will be checked against the actual order of the enumeration and raise an error if the two do not match:
     1779\begin{python}
     1780>>> class Color(Enum):
     1781...     _order_ = 'RED GREEN BLUE'
     1782...     RED = 1
     1783...     BLUE = 3
     1784...     GREEN = 2
     1785...
     1786Traceback (most recent call last):
     1787...
     1788TypeError: member order does not match _order_:
     1789  ['RED', 'BLUE', 'GREEN']
     1790  ['RED', 'GREEN', 'BLUE']
     1791\end{python}
     1792Note: In Python 2 code the @_order_@ attribute is necessary as definition order is lost before it can be recorded.
     1793
     1794\subsection{\lstinline{_Private__names}}
     1795
     1796Private names are not converted to enum members, but remain normal attributes.
     1797
     1798Changed in version 3.11.
     1799
     1800\subsection{\lstinline{Enum} member type}
     1801
     1802@Enum@ members are instances of their enum class, and are normally accessed as @EnumClass.member@.
     1803In certain situations, such as writing custom enum behavior, being able to access one member directly from another is useful, and is supported;
     1804however, in order to avoid name clashes between member names and attributes/methods from mixed-in classes, upper-case names are strongly recommended.
     1805
     1806Changed in version 3.5.
     1807
     1808\subsection{Creating members that are mixed with other data types}
     1809
     1810When subclassing other data types, such as @int@ or @str@, with an @Enum@, all values after the = @are@ passed to that data type's constructor. For example:
     1811\begin{python}
     1812>>> class MyEnum(IntEnum):      # help(int) -> int(x, base=10) -> integer
     1813...     example = '11', 16      # so x='11' and base=16
     1814...
     1815MyEnum.example.value        # and hex(11) is...
     181617
     1817\end{python}
     1818
     1819\subsection{\lstinline{Boolean} value of \lstinline{Enum} classes and members}
     1820
     1821Enum classes that are mixed with non-@Enum@ types (such as @int@, @str@, etc.) are evaluated according to the mixed-in type's rules;
     1822otherwise, all members evaluate as @True@.
     1823To make your own enum's boolean evaluation depend on the member's value add the following to your class:
     1824\begin{python}
     1825def __bool__(self):
     1826        return bool(self.value)
     1827\end{python}
     1828Plain @Enum@ classes always evaluate as @True@.
     1829
     1830\subsection{\lstinline{Enum} classes with methods}
     1831
     1832If you give your enum subclass extra methods, like the Planet class below, those methods will show up in a dir() of the member, but not of the class:
     1833\begin{python}
     1834>>> dir(Planet)                         
     1835['EARTH', 'JUPITER', 'MARS', 'MERCURY', 'NEPTUNE', 'SATURN', 'URANUS', 'VENUS',
     1836 '__class__', '__doc__', '__members__', '__module__']
     1837>>> dir(Planet.EARTH)                   
     1838['__class__', '__doc__', '__module__', 'mass', 'name', 'radius', 'surface_gravity', 'value']
     1839\end{python}
     1840
     1841\subsection{Combining members of \lstinline{Flag}}
     1842
     1843Iterating over a combination of @Flag@ members will only return the members that are comprised of a single bit:
     1844\begin{python}
     1845>>> class Color(Flag):
     1846...     RED = auto()
     1847...     GREEN = auto()
     1848...     BLUE = auto()
     1849...     MAGENTA = RED | BLUE
     1850...     YELLOW = RED | GREEN
     1851...     CYAN = GREEN | BLUE
     1852...
     1853>>> Color(3)  # named combination
     1854<Color.YELLOW: 3>
     1855>>> Color(7)      # not named combination
     1856<Color.RED|GREEN|BLUE: 7>
     1857\end{python}
     1858
     1859\subsection{\lstinline{Flag} and \lstinline{IntFlag} minutia}
     1860
     1861Using the following snippet for our examples:
     1862\begin{python}
     1863>>> class Color(IntFlag):
     1864...     BLACK = 0
     1865...     RED = 1
     1866...     GREEN = 2
     1867...     BLUE = 4
     1868...     PURPLE = RED | BLUE
     1869...     WHITE = RED | GREEN | BLUE
     1870...
     1871\end{python}
     1872the following are true:
     1873\begin{itemize}
     1874\item
     1875single-bit flags are canonical
     1876\item
     1877multi-bit and zero-bit flags are aliases
     1878\item
     1879only canonical flags are returned during iteration:
     1880\begin{python}
     1881>>> list(Color.WHITE)
     1882[<Color.RED: 1>, <Color.GREEN: 2>, <Color.BLUE: 4>]
     1883\end{python}
     1884negating a flag or flag set returns a new flag/flag set with the corresponding positive integer value:
     1885\begin{python}
     1886>>> Color.BLUE
     1887<Color.BLUE: 4>
     1888
     1889>>> ~Color.BLUE
     1890<Color.RED|GREEN: 3>
     1891\end{python}
     1892\item
     1893names of pseudo-flags are constructed from their members' names:
     1894\begin{python}
     1895>>> (Color.RED | Color.GREEN).name
     1896'RED|GREEN'
     1897\end{python}
     1898\item
     1899multi-bit flags, aka aliases, can be returned from operations:
     1900\begin{python}
     1901>>> Color.RED | Color.BLUE
     1902<Color.PURPLE: 5>
     1903
     1904>>> Color(7)  # or Color(-1)
     1905<Color.WHITE: 7>
     1906
     1907>>> Color(0)
     1908<Color.BLACK: 0>
     1909\end{python}
     1910\item
     1911membership / containment checking: zero-valued flags are always considered to be contained:
     1912\begin{python}
     1913>>> Color.BLACK in Color.WHITE
     1914True
     1915\end{python}
     1916otherwise, only if all bits of one flag are in the other flag will True be returned:
     1917\begin{python}
     1918>>> Color.PURPLE in Color.WHITE
     1919True
     1920
     1921>>> Color.GREEN in Color.PURPLE
     1922False
     1923\end{python}
     1924\end{itemize}
     1925There is a new boundary mechanism that controls how out-of-range / invalid bits are handled: @STRICT@, @CONFORM@, @EJECT@, and @KEEP@:
     1926\begin{itemize}
     1927\item
     1928@STRICT@ --> raises an exception when presented with invalid values
     1929\item
     1930@CONFORM@ --> discards any invalid bits
     1931\item
     1932@EJECT@ --> lose Flag status and become a normal int with the given value
     1933\item
     1934@KEEP@ --> keep the extra bits
     1935\begin{itemize}
     1936\item
     1937keeps Flag status and extra bits
     1938\item
     1939extra bits do not show up in iteration
     1940\item
     1941extra bits do show up in repr() and str()
     1942\end{itemize}
     1943\end{itemize}
     1944The default for @Flag@ is @STRICT@, the default for @IntFlag@ is @EJECT@, and the default for @_convert_@ is @KEEP@ (see @ssl.Options@ for an example of when @KEEP@ is needed).
     1945
     1946\section{How are Enums and Flags different?}
     1947
     1948Enums have a custom metaclass that affects many aspects of both derived @Enum@ classes and their instances (members).
     1949
     1950\subsection{Enum Classes}
     1951
     1952The @EnumType@ metaclass is responsible for providing the @__contains__()@, @__dir__()@, @__iter__()@ and other methods that allow one to do things with an @Enum@ class that fail on a typical class, such as @list(Color)@ or @some_enum_var@ in @Color@.
     1953@EnumType@ is responsible for ensuring that various other methods on the final @Enum@ class are correct (such as @__new__()@, @__getnewargs__()@, @__str__()@ and @__repr__()@).
     1954
     1955\subsection{Flag Classes}
     1956
     1957Flags have an expanded view of aliasing: to be canonical, the value of a flag needs to be a power-of-two value, and not a duplicate name.
     1958So, in addition to the @Enum@ definition of alias, a flag with no value (a.k.a. 0) or with more than one power-of-two value (e.g. 3) is considered an alias.
     1959
     1960\subsection{Enum Members (aka instances)}
     1961
     1962The most interesting thing about enum members is that they are singletons.
     1963@EnumType@ creates them all while it is creating the enum class itself, and then puts a custom @__new__()@ in place to ensure that no new ones are ever instantiated by returning only the existing member instances.
     1964
     1965\subsection{Flag Members}
     1966
     1967Flag members can be iterated over just like the @Flag@ class, and only the canonical members will be returned.
     1968For example:
     1969\begin{python}
     1970>>> list(Color)
     1971[<Color.RED: 1>, <Color.GREEN: 2>, <Color.BLUE: 4>]
     1972\end{python}
     1973(Note that BLACK, PURPLE, and WHITE do not show up.)
     1974
     1975Inverting a flag member returns the corresponding positive value, rather than a negative value -- for example:
     1976\begin{python}
     1977>>> ~Color.RED
     1978<Color.GREEN|BLUE: 6>
     1979\end{python}
     1980Flag members have a length corresponding to the number of power-of-two values they contain. For example:
     1981\begin{python}
     1982>>> len(Color.PURPLE)
     19832
     1984\end{python}
     1985
     1986\subsection{Enum Cookbook}
     1987
     1988While @Enum@, @IntEnum@, @StrEnum@, @Flag@, and @IntFlag@ are expected to cover the majority of use-cases, they cannot cover them all. Here are recipes for some different types of enumerations that can be used directly, or as examples for creating one's own.
     1989
     1990\subsection{Omitting values}
     1991
     1992In many use-cases, one doesn't care what the actual value of an enumeration is. There are several ways to define this type of simple enumeration:
     1993\begin{itemize}
     1994\item
     1995use instances of auto for the value
     1996\item
     1997use instances of object as the value
     1998\item
     1999use a descriptive string as the value
     2000\item
     2001use a tuple as the value and a custom @__new__()@ to replace the tuple with an @int@ value
     2002\end{itemize}
     2003Using any of these methods signifies to the user that these values are not important, and also enables one to add, remove, or reorder members without having to renumber the remaining members.
     2004
     2005\subsection{Using \lstinline{auto}}
     2006
     2007Using @auto@ would look like:
     2008\begin{python}
     2009>>> class Color(Enum):
     2010...     RED = auto()
     2011...     BLUE = auto()
     2012...     GREEN = auto()
     2013...
     2014>>> Color.GREEN
     2015<Color.GREEN: 3>
     2016\end{python}
     2017
     2018\subsection{Using \lstinline{object}}
     2019
     2020Using @object@ would look like:
     2021\begin{python}
     2022>>> class Color(Enum):
     2023...     RED = object()
     2024...     GREEN = object()
     2025...     BLUE = object()
     2026...
     2027>>> Color.GREEN                         
     2028<Color.GREEN: <object object at 0x...>>
     2029\end{python}
     2030This is also a good example of why you might want to write your own @__repr__()@:
     2031\begin{python}
     2032>>> class Color(Enum):
     2033...     RED = object()
     2034...     GREEN = object()
     2035...     BLUE = object()
     2036...     def __repr__(self):
     2037...         return "<%s.%s>" % (self.__class__.__name__, self._name_)
     2038...
     2039>>> Color.GREEN
     2040<Color.GREEN>
     2041\end{python}
     2042
     2043\subsection{Using a descriptive string}
     2044
     2045Using a string as the value would look like:
     2046\begin{python}
     2047>>> class Color(Enum):
     2048...     RED = 'stop'
     2049...     GREEN = 'go'
     2050...     BLUE = 'too fast!'
     2051...
     2052>>> Color.GREEN
     2053<Color.GREEN: 'go'>
     2054\end{python}
     2055
     2056\subsection{Using a custom \lstinline{__new__()}}
     2057
     2058Using an auto-numbering @__new__()@ would look like:
     2059\begin{python}
     2060>>> class AutoNumber(Enum):
     2061...     def __new__(cls):
     2062...         value = len(cls.__members__) + 1
     2063...         obj = object.__new__(cls)
     2064...         obj._value_ = value
     2065...         return obj
     2066...
     2067>>> class Color(AutoNumber):
     2068...     RED = ()
     2069...     GREEN = ()
     2070...     BLUE = ()
     2071...
     2072>>> Color.GREEN
     2073<Color.GREEN: 2>
     2074\end{python}
     2075To make a more general purpose @AutoNumber@, add @*args@ to the signature:
     2076\begin{python}
     2077>>> class AutoNumber(Enum):
     2078...     def __new__(cls, *args):      # this is the only change from above
     2079...         value = len(cls.__members__) + 1
     2080...         obj = object.__new__(cls)
     2081...         obj._value_ = value
     2082...         return obj
     2083\end{python}
     2084Then when you inherit from @AutoNumber@ you can write your own @__init__@ to handle any extra arguments:
     2085\begin{python}
     2086>>> class Swatch(AutoNumber):
     2087...     def __init__(self, pantone='unknown'):
     2088...         self.pantone = pantone
     2089...     AUBURN = '3497'
     2090...     SEA_GREEN = '1246'
     2091...     BLEACHED_CORAL = () # New color, no Pantone code yet!
     2092...
     2093>>> Swatch.SEA_GREEN
     2094<Swatch.SEA_GREEN: 2>
     2095>>> Swatch.SEA_GREEN.pantone
     2096'1246'
     2097>>> Swatch.BLEACHED_CORAL.pantone
     2098'unknown'
     2099\end{python}
     2100Note: The @__new__()@ method, if defined, is used during creation of the Enum members;
     2101it is then replaced by Enum's @__new__()@ which is used after class creation for lookup of existing members.
     2102
     2103Warning: Do not call @super().__new__()@, as the lookup-only @__new__@ is the one that is found;
     2104instead, use the data type directly -- e.g.:
     2105\begin{python}
     2106obj = int.__new__(cls, value)
     2107\end{python}
     2108
     2109\subsection{OrderedEnum}
     2110
     2111An ordered enumeration that is not based on @IntEnum@ and so maintains the normal @Enum@ invariants (such as not being comparable to other enumerations):
     2112\begin{python}
     2113>>> class OrderedEnum(Enum):
     2114...     def __ge__(self, other):
     2115...         if self.__class__ is other.__class__:
     2116...             return self.value >= other.value
     2117...         return NotImplemented
     2118...     def __gt__(self, other):
     2119...         if self.__class__ is other.__class__:
     2120...             return self.value > other.value
     2121...         return NotImplemented
     2122...     def __le__(self, other):
     2123...         if self.__class__ is other.__class__:
     2124...             return self.value <= other.value
     2125...         return NotImplemented
     2126...     def __lt__(self, other):
     2127...         if self.__class__ is other.__class__:
     2128...             return self.value < other.value
     2129...         return NotImplemented
     2130...
     2131>>> class Grade(OrderedEnum):
     2132...     A = 5
     2133...     B = 4
     2134...     C = 3
     2135...     D = 2
     2136...     F = 1
     2137>>> Grade.C < Grade.A
     2138True
     2139\end{python}
     2140
     2141\subsection{DuplicateFreeEnum}
     2142
     2143Raises an error if a duplicate member value is found instead of creating an alias:
     2144\begin{python}
     2145>>> class DuplicateFreeEnum(Enum):
     2146...     def __init__(self, *args):
     2147...         cls = self.__class__
     2148...         if any(self.value == e.value for e in cls):
     2149...             a = self.name
     2150...             e = cls(self.value).name
     2151...             raise ValueError(
     2152...                 "aliases not allowed in DuplicateFreeEnum:  %r --> %r"
     2153...                 % (a, e))
     2154>>> class Color(DuplicateFreeEnum):
     2155...     RED = 1
     2156...     GREEN = 2
     2157...     BLUE = 3
     2158...     GRENE = 2
     2159...
     2160Traceback (most recent call last):
     2161  ...
     2162ValueError: aliases not allowed in DuplicateFreeEnum:  'GRENE' --> 'GREEN'
     2163\end{python}
     2164Note: This is a useful example for subclassing Enum to add or change other behaviors as well as disallowing aliases.
     2165If the only desired change is disallowing aliases, the @unique()@ decorator can be used instead.
     2166
     2167\subsection{Planet}
     2168
     2169If @__new__()@ or @__init__()@ is defined, the value of the enum member will be passed to those methods:
     2170\begin{figure}
     2171\begin{python}
     2172from enum import Enum
     2173class Planet(Enum):
     2174        MERCURY = ( 3.303E23, 2.4397E6 )
     2175        VENUS       = ( 4.869E24, 6.0518E6 )
     2176        EARTH       = (5.976E24, 6.37814E6)
     2177        MARS         = (6.421E23, 3.3972E6)
     2178        JUPITER    = (1.9E27,   7.1492E7)
     2179        SATURN     = (5.688E26, 6.0268E7)
     2180        URANUS    = (8.686E25, 2.5559E7)
     2181        NEPTUNE  = (1.024E26, 2.4746E7)
     2182        def __init__( self, mass, radius ):
     2183                self.mass = mass                # in kilograms
     2184                self.radius = radius    # in meters
     2185        def surface_gravity( self ):
     2186                # universal gravitational constant  (m3 kg-1 s-2)
     2187                G = 6.67300E-11
     2188                return G * self.mass / (self.radius * self.radius)
     2189for p in Planet:
     2190        print( f"{p.name}: {p.value}" )
     2191
     2192MERCURY: (3.303e+23, 2439700.0)
     2193VENUS: (4.869e+24, 6051800.0)
     2194EARTH: (5.976e+24, 6378140.0)
     2195MARS: (6.421e+23, 3397200.0)
     2196JUPITER: (1.9e+27, 71492000.0)
     2197SATURN: (5.688e+26, 60268000.0)
     2198URANUS: (8.686e+25, 25559000.0)
     2199NEPTUNE: (1.024e+26, 24746000.0)
     2200\end{python}
     2201\caption{Python Planet Example}
     2202\label{f:PythonPlanetExample}
     2203\end{figure}
     2204
     2205
     2206\subsection{TimePeriod}
     2207
     2208An example to show the @_ignore_@ attribute in use:
     2209\begin{python}
     2210>>> from datetime import timedelta
     2211>>> class Period(timedelta, Enum):
     2212...     "different lengths of time"
     2213...     _ignore_ = 'Period i'
     2214...     Period = vars()
     2215...     for i in range(367):
     2216...         Period['day_%d' % i] = i
     2217...
     2218>>> list(Period)[:2]
     2219[<Period.day_0: datetime.timedelta(0)>, <Period.day_1: datetime.timedelta(days=1)>]
     2220>>> list(Period)[-2:]
     2221[<Period.day_365: datetime.timedelta(days=365)>, <Period.day_366: datetime.timedelta(days=366)>]
     2222\end{python}
     2223
     2224\subsection{Subclassing EnumType}
     2225
     2226While most enum needs can be met by customizing @Enum@ subclasses, either with class decorators or custom functions, @EnumType@ can be subclassed to provide a different Enum experience.
    10932227
    10942228
     
    11602294In summary, an OCaml variant is a singleton value rather than a set of possibly ordered values, and hence, has no notion of enumerabilty.
    11612295Therefore it is not an enumeration, except for the simple opaque (nullary) case.
    1162 
    1163 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    11642296
    11652297\begin{comment}
     
    13102442To: Gregor Richards <gregor.richards@uwaterloo.ca>, Peter Buhr <pabuhr@uwaterloo.ca>
    13112443CC: Michael Leslie Brooks <mlbrooks@uwaterloo.ca>, Fangren Yu <f37yu@uwaterloo.ca>,
    1312         Jiada Liang <j82liang@uwaterloo.ca>
     2444    Jiada Liang <j82liang@uwaterloo.ca>
    13132445Subject: Re: Re:
    13142446Date: Thu, 21 Mar 2024 14:26:36 +0000
     
    13182450
    13192451enum Example {
    1320         Label,
    1321         Name = 10,
    1322         Tag = 3,
     2452    Label,
     2453    Name = 10,
     2454    Tag = 3,
    13232455};
    13242456
     
    14102542auto-init               &               &               &               &               &               &               &               &               &               &               & \CM   & \CM   & \CM   \\
    14112543\hline
    1412 (Un)Scoped              &               &               &               &               &               &               &               &               &               &               & U             & U/S   & U/S   \\
     2544(un)scoped              &               &               &               &               &               &               &               &               &               &               & U             & U/S   & U/S   \\
    14132545\hline
    14142546overload                &               & \CM   &               &               &               &               &               &               &               &               &               & \CM   & \CM   \\
  • doc/theses/jiada_liang_MMath/uw-ethesis.tex

    rb166b1c rf30be51f  
    106106\lstnewenvironment{rust}[1][]{\lstset{language=Rust,escapechar=\$,moredelim=**[is][\color{red}]{@}{@},}\lstset{#1}}{}
    107107\lstnewenvironment{swift}[1][]{\lstset{language=Swift,escapechar=\$,moredelim=**[is][\color{red}]{@}{@},}\lstset{#1}}{}
    108 \lstnewenvironment{python}[1][]{\lstset{language=Python,morekeywords={match,case},
    109         escapechar=\$,moredelim=**[is][\color{red}]{!}{!},}\lstset{#1}}{}
     108\lstnewenvironment{python}[1][]{\lstset{language=Python,escapechar=\$,moredelim=**[is][\color{red}]{@}{@},}\lstset{#1}}{}
    110109\lstnewenvironment{ocaml}[1][]{\lstset{language=OCaml,escapechar=\$,moredelim=**[is][\color{red}]{@}{@},}\lstset{#1}}{}
    111110
  • src/Parser/parser.yy

    rb166b1c rf30be51f  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Jun 11 21:32:15 2024
    13 // Update Count     : 6641
     12// Last Modified On : Tue Jun 11 16:56:42 2024
     13// Update Count     : 6638
    1414//
    1515
     
    387387// names and constants: lexer differentiates between identifier and typedef names
    388388%token<tok> IDENTIFIER          TYPEDIMname             TYPEDEFname             TYPEGENname
    389 %token<tok> TIMEOUT                     WAND    WOR             CATCH                   RECOVER                 CATCHRESUME             FIXUP           FINALLY         // CFA
     389%token<tok> TIMEOUT                     WAND    WOR                     CATCH                   RECOVER                 CATCHRESUME             FIXUP           FINALLY         // CFA
    390390%token<tok> INTEGERconstant     CHARACTERconstant       STRINGliteral
    391391%token<tok> DIRECTIVE
     
    493493%type<decl> exception_declaration
    494494
    495 %type<decl> field_declaration_list_opt field_declaration field_declaring_list_opt field_declarator field_abstract_list_opt field_abstract
     495%type<decl> field_declaration_list_opt field_declaration field_declaring_list_opt field_declaring_list field_declarator field_abstract_list_opt field_abstract
    496496%type<expr> field field_name_list field_name fraction_constants_opt
    497497
     
    678678        | '@'                                                                                           // CFA
    679679                { Token tok = { new string( DeclarationNode::anonymous.newName() ), yylval.tok.loc }; $$ = tok; }
    680         ;
    681 
    682 identifier_or_type_name:
    683         identifier
    684         | TYPEDEFname
    685         | TYPEGENname
    686680        ;
    687681
     
    817811                //       z.E;  // lexer returns E is TYPEDEFname
    818812                //   }
    819         | postfix_expression '.' identifier_or_type_name
     813        | postfix_expression '.' identifier
     814                { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_varref( yylloc, $3 ) ) ); }
     815        | postfix_expression '.' TYPEDEFname                            // CFA, SKULLDUGGERY
     816                { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_varref( yylloc, $3 ) ) ); }
     817        | postfix_expression '.' TYPEGENname                            // CFA, SKULLDUGGERY
    820818                { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_varref( yylloc, $3 ) ) ); }
    821819
     
    16151613enum_key:
    16161614        TYPEDEFname
    1617         | ENUM identifier_or_type_name
     1615        | ENUM TYPEDEFname
    16181616        ;
    16191617
     
    26942692        // empty
    26952693                { $$ = nullptr; }
    2696         | field_declarator
    2697         | field_declaring_list_opt ',' attribute_list_opt field_declarator
     2694        | field_declaring_list
     2695        ;
     2696
     2697field_declaring_list:
     2698        field_declarator
     2699        | field_declaring_list ',' attribute_list_opt field_declarator
    26982700                { $$ = $1->set_last( $4->addQualifiers( $3 ) ); }
    26992701        ;
     
    29592961        ;
    29602962
     2963identifier_or_type_name:
     2964        identifier
     2965        | TYPEDEFname
     2966        | TYPEGENname
     2967        ;
     2968
    29612969type_no_function:                                                                               // sizeof, alignof, cast (constructor)
    29622970        cfa_abstract_declarator_tuple                                           // CFA
     
    32223230        // empty, input file
    32233231        | external_definition_list
    3224                 { parseTree = parseTree ? parseTree->set_last( $1 ) : $1; }
     3232                { parseTree = parseTree ? parseTree->set_last( $1 ) : $1;       }
    32253233        ;
    32263234
     
    34803488
    34813489attr_name:                                                                                              // GCC
    3482         identifier_or_type_name
     3490        IDENTIFIER
     3491        | quasi_keyword
     3492        | TYPEDEFname
     3493        | TYPEGENname
    34833494        | FALLTHROUGH
    34843495                { $$ = Token{ new string( "fallthrough" ), { nullptr, -1 } }; }
Note: See TracChangeset for help on using the changeset viewer.