Ignore:
Timestamp:
Mar 25, 2024, 7:15:30 PM (6 months ago)
Author:
JiadaL <j82liang@…>
Branches:
master
Children:
d734fa1
Parents:
df78cce (diff), bf050c5 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

File:
1 edited

Legend:

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

    rdf78cce r486caad  
    22\label{s:RelatedWork}
    33
     4\begin{comment}
    45An algebraic data type (ADT) can be viewed as a recursive sum of product types.
    56A sum type lists values as members.
     
    1516Enumerated types are a special case of product/sum types with non-mutable fields, \ie initialized (constructed) once at the type's declaration, possible restricted to compile-time initialization.
    1617Values of algebraic types are access by subscripting, field qualification, or type (pattern) matching.
     18\end{comment}
    1719
    1820Enumeration types exist in many popular programming languages, both past and present, \eg Pascal~\cite{Pascal}, Ada~\cite{Ada}, \Csharp~\cite{Csharp}, OCaml~\cite{OCaml} \CC, Go~\cite{Go}, Java~\cite{Java}, Modula-3~\cite{Modula-3}, Rust~\cite{Rust}, Swift~\cite{Swift}, Python~\cite{Python}.
     
    2022
    2123\section{Pascal}
     24\label{s:Pascal}
    2225\lstnewenvironment{pascal}[1][]{\lstset{language=pascal,escapechar=\$,moredelim=**[is][\color{red}]{@}{@},}\lstset{#1}}{}
    2326
     
    2730                 PI = 3.14159;   Plus = '+';   Fred = 'Fred';
    2831\end{pascal}
    29 Here, there is no enumeration because there is no specific type (pseudo enumeration).
     32This mechanism is not an enumeration because there is no specific type (pseudo enumeration).
    3033Hence, there is no notion of a (possibly ordered) set, modulo the \lstinline[language=pascal]{set of} type.
    3134The type of each constant name (enumerator) is inferred from the constant-expression type.
     
    8184with Ada.Text_IO; use Ada.Text_IO;
    8285procedure test is
    83    type RGB is ( @Red@, Green, Blue );
    84    type Traffic_Light is ( @Red@, Yellow, Green );         -- overload
    85    procedure @Red@( Colour : RGB ) is begin            -- overload
    86        Put_Line( "Colour is " & RGB'Image( Colour ) );
    87    end Red;
    88    procedure @Red@( TL : Traffic_Light ) is begin       -- overload
    89        Put_Line( "Light is " & Traffic_Light'Image( TL ) );
    90    end Red;
     86        type RGB is ( @Red@, Green, Blue );
     87        type Traffic_Light is ( @Red@, Yellow, Green );         -- overload
     88        procedure @Red@( Colour : RGB ) is begin            -- overload
     89                Put_Line( "Colour is " & RGB'Image( Colour ) );
     90        end Red;
     91        procedure @Red@( TL : Traffic_Light ) is begin       -- overload
     92                Put_Line( "Light is " & Traffic_Light'Image( TL ) );
     93        end Red;
    9194begin
    92     @Red@( Blue );                               -- RGB
    93     @Red@( Yellow );                            -- Traffic_Light
    94     @Red@( @RGB'(Red)@ );               -- ambiguous without cast
     95        @Red@( Blue );                           -- RGB
     96        @Red@( Yellow );                                -- Traffic_Light
     97        @Red@( @RGB'(Red)@ );           -- ambiguous without cast
    9598end test;
    9699\end{ada}
     
    224227\lstnewenvironment{c++}[1][]{\lstset{language=[GNU]C++,escapechar=\$,moredelim=**[is][\color{red}]{@}{@},}\lstset{#1}}{}
    225228
    226 \CC is largely backwards compatible with C, so it inherited C's enumerations.
    227 However, the following non-backwards compatible changes have been made.
     229\CC has the equivalent of Pascal typed @const@ declarations \see{\VRef{s:Pascal}}, with static and dynamic initialization.
     230\begin{c++}
     231const auto one = 0 + 1;                                 $\C{// static intialization}$
     232const auto NULL = nullptr;
     233const auto PI = 3.14159;
     234const auto Plus = '+';
     235const auto Fred = "Fred";
     236const auto Mon = 0, Tue = Mon + 1, Wed = Tue + 1, Thu = Wed + 1, Fri = Thu + 1,
     237                                Sat = Fri + 1, Sun = Sat + 1;
     238int sa[Sun];
     239const auto r = random();                                $\C{// dynamic intialization}$
     240int da[r];                                                              $\C{// VLA}$
     241\end{c++}
     242Statically initialized identifiers may appear in any constant-expression context, \eg @case@.
     243Dynamically intialized identifiers may appear as array dimensions in @g++@, which allows variable-sized arrays.
     244Interestingly, global \CC @const@ declarations are implicitly marked @static@ (@r@ rather than @R@).
     245\begin{c++}
     246$\$$ nm test.o
     2470000000000000018 @r@ Mon
     248\end{c++}
     249
     250\CC enumeration is largely backwards compatible with C, so it inherited C's enumerations.
     251However, the following non-backwards compatible changes are made.
    228252
    229253\begin{cquote}
     
    423447\begin{Go}
    424448const ( Mon = iota; Tue; Wed; // 0, 1, 2
    425          @Thu = 10@; Fri; Sat; Sun ) // 10, 10, 10, 10
     449        @Thu = 10@; Fri; Sat; Sun ) // 10, 10, 10, 10
    426450\end{Go}
    427451Auto-incrementing can be restarted with an expression containing \emph{one} \lstinline[language=Go]{iota}.
     
    429453const ( V1 = iota; V2; @V3 = 7;@ V4 = @iota@; V5 ) // 0 1 7 3 4
    430454const ( Mon = iota; Tue; Wed; // 0, 1, 2
    431          @Thu = 10;@ Fri = @iota - Wed + Thu - 1@; Sat; Sun ) // 10, 11, 12, 13
     455        @Thu = 10;@ Fri = @iota - Wed + Thu - 1@; Sat; Sun ) // 10, 11, 12, 13
    432456\end{Go}
    433457Note, \lstinline[language=Go]{iota} is advanced for an explicitly initialized enumerator, like the underscore @_@ identifier.
     
    584608\lstnewenvironment{rust}[1][]{\lstset{language=Rust,escapechar=\$,moredelim=**[is][\color{red}]{@}{@},}\lstset{#1}}{}
    585609
    586 Enumerations
     610Rust provides a scoped enumeration based on variant types.
     611% An enumeration, also referred to as an enum, is a simultaneous definition of a nominal enumerated type as well as a set of constructors, that can be used to create or pattern-match values of the corresponding enumerated type.
     612An enumeration without constructors is called field-less.
    587613\begin{rust}
    588         Syntax
    589         Enumeration :
    590            enum IDENTIFIER  GenericParams? WhereClause? { EnumItems? }
    591 
    592         EnumItems :
    593            EnumItem ( , EnumItem )* ,?
    594 
    595         EnumItem :
    596            OuterAttribute* Visibility?
    597            IDENTIFIER ( EnumItemTuple | EnumItemStruct )? EnumItemDiscriminant?
    598 
    599         EnumItemTuple :
    600            ( TupleFields? )
    601 
    602         EnumItemStruct :
    603            { StructFields? }
    604 
    605         EnumItemDiscriminant :
    606            = Expression
     614enum Week { Mon, Tues, Wed, Thu, Fri, Sat, Sun@,@ }
     615let mut week: Week = Week::Mon;
     616week = Week::Fri;
    607617\end{rust}
    608 An enumeration, also referred to as an enum, is a simultaneous definition of a nominal enumerated type as well as a set of constructors, that can be used to create or pattern-match values of the corresponding enumerated type.
    609 
    610 Enumerations are declared with the keyword enum.
    611 
    612 An example of an enum item and its use:
     618A field-less enumeration with only unit variants is called unit-only.
    613619\begin{rust}
    614 enum Animal {
    615         Dog,
    616         Cat,
    617 }
    618 
    619 let mut a: Animal = Animal::Dog;
    620 a = Animal::Cat;
     620enum Week { Mon = 0, Tues = 1, Wed = 2, Thu = 3, Fri = 4, Sat = 5, Sun = 6 }
    621621\end{rust}
    622622Enum constructors can have either named or unnamed fields:
    623623\begin{rust}
    624624enum Animal {
    625         Dog(String, f64),
    626         Cat { name: String, weight: f64 },
    627 }
    628 
     625        Dog( String, f64 ),
     626        Cat{ name: String, weight: f64 },
     627}
    629628let mut a: Animal = Animal::Dog("Cocoa".to_string(), 37.2);
    630629a = Animal::Cat { name: "Spotty".to_string(), weight: 2.7 };
    631630\end{rust}
    632 In this example, Cat is a struct-like enum variant, whereas Dog is simply called an enum variant.
    633 
    634 An enum where no constructors contain fields are called a field-less enum. For example, this is a fieldless enum:
     631Here, @Dog@ is an @enum@ variant, whereas @Cat@ is a struct-like variant.
     632
     633Each @enum@ type has an implicit integer tag (discriminant), with a unique value for each variant type.
     634Like a C enumeration, the tag values for the variant types start at 0 with auto incrementing.
     635The tag is re-purposed for enumeration by allowing it to be explicitly set, and auto incrmenting continues from that value.
     636\begin{cquote}
     637\sf\setlength{\tabcolsep}{3pt}
     638\begin{tabular}{rcccccccr}
     639@enum@ Week \{  & Mon,  & Tue,  & Wed = 2,      & Thu = 10,     & Fri,  & Sat = 5,      & Sun   & \};   \\
     640\rm tags                & 0             & 1             & 2                     & 10            & 11    & 5                     & 6             &               \\
     641\end{tabular}
     642\end{cquote}
     643In general, the tag can only be read as an opaque reference for comparison.
    635644\begin{rust}
    636 enum Fieldless {
    637         Tuple(),
    638         Struct{},
    639         Unit,
    640 }
     645if mem::discriminant(&week) == mem::discriminant(&Week::Mon) ...
    641646\end{rust}
    642 If a field-less enum only contains unit variants, the enum is called an unit-only enum. For example:
     647If the enumeration is unit-only, or field-less with no explicit discriminants and where only unit variants are explicit, then the discriminant is accessible with a numeric cast.
    643648\begin{rust}
    644 enum Enum {
    645         Foo = 3,
    646         Bar = 2,
    647         Baz = 1,
    648 }
    649 \end{rust}
    650 
    651 \subsection{Discriminants}
    652 
    653 Each enum instance has a discriminant: an integer logically associated to it that is used to determine which variant it holds.
    654 
    655 Under the default representation, the discriminant is interpreted as an isize value. However, the compiler is allowed to use a smaller type (or another means of distinguishing variants) in its actual memory layout.
    656 
    657 \subsection{Assigning discriminant values}
    658 
    659 \subsection{Explicit discriminants}
    660 
    661 In two circumstances, the discriminant of a variant may be explicitly set by following the variant name with = and a constant expression:
    662 
    663         if the enumeration is "unit-only".
    664 
    665         if a primitive representation is used. For example:
    666 \begin{rust}
    667         #[repr(u8)]
    668         enum Enum {
    669                 Unit = 3,
    670                 Tuple(u16),
    671                 Struct {
    672                         a: u8,
    673                         b: u16,
    674                 } = 1,
    675         }
    676 \end{rust}
    677 
    678 \subsection{Implicit discriminants}
    679 
    680 If a discriminant for a variant is not specified, then it is set to one higher than the discriminant of the previous variant in the declaration. If the discriminant of the first variant in the declaration is unspecified, then it is set to zero.
    681 \begin{rust}
    682 enum Foo {
    683         Bar,                    // 0
    684         Baz = 123,        // 123
    685         Quux,              // 124
    686 }
    687 
    688 let baz_discriminant = Foo::Baz as u32;
    689 assert_eq!(baz_discriminant, 123);
    690 \end{rust}
    691 
    692 \subsection{Restrictions}
    693 
    694 It is an error when two variants share the same discriminant.
    695 \begin{rust}
    696 enum SharedDiscriminantError {
    697         SharedA = 1,
    698         SharedB = 1
    699 }
    700 
    701 enum SharedDiscriminantError2 {
    702         Zero,      // 0
    703         One,            // 1
    704         OneToo = 1  // 1 (collision with previous!)
    705 }
    706 \end{rust}
    707 It is also an error to have an unspecified discriminant where the previous discriminant is the maximum value for the size of the discriminant.
    708 \begin{rust}
    709 #[repr(u8)]
    710 enum OverflowingDiscriminantError {
    711         Max = 255,
    712         MaxPlusOne // Would be 256, but that overflows the enum.
    713 }
    714 
    715 #[repr(u8)]
    716 enum OverflowingDiscriminantError2 {
    717         MaxMinusOne = 254, // 254
    718         Max,                       // 255
    719         MaxPlusOne               // Would be 256, but that overflows the enum.
    720 }
    721 \end{rust}
    722 
    723 \subsection{Accessing discriminant}
    724 
    725 \begin{rust}
    726 Via mem::discriminant
    727 \end{rust}
    728 @mem::discriminant@ returns an opaque reference to the discriminant of an enum value which can be compared. This cannot be used to get the value of the discriminant.
    729 
    730 \subsection{Casting}
    731 
    732 If an enumeration is unit-only (with no tuple and struct variants), then its discriminant can be directly accessed with a numeric cast; e.g.:
    733 \begin{rust}
    734 enum Enum {
    735         Foo,
    736         Bar,
    737         Baz,
    738 }
    739 
    740 assert_eq!(0, Enum::Foo as isize);
    741 assert_eq!(1, Enum::Bar as isize);
    742 assert_eq!(2, Enum::Baz as isize);
    743 \end{rust}
    744 Field-less enums can be casted if they do not have explicit discriminants, or where only unit variants are explicit.
    745 \begin{rust}
    746 enum Fieldless {
    747         Tuple(),
    748         Struct{},
    749         Unit,
    750 }
    751 
    752 assert_eq!(0, Fieldless::Tuple() as isize);
    753 assert_eq!(1, Fieldless::Struct{} as isize);
    754 assert_eq!(2, Fieldless::Unit as isize);
    755 \end{rust}
    756 \begin{rust}
    757 #[repr(u8)]
    758 enum FieldlessWithDiscrimants {
    759         First = 10,
    760         Tuple(),
    761         Second = 20,
    762         Struct{},
    763         Unit,
    764 }
    765 
    766 assert_eq!(10, FieldlessWithDiscrimants::First as u8);
    767 assert_eq!(11, FieldlessWithDiscrimants::Tuple() as u8);
    768 assert_eq!(20, FieldlessWithDiscrimants::Second as u8);
    769 assert_eq!(21, FieldlessWithDiscrimants::Struct{} as u8);
    770 assert_eq!(22, FieldlessWithDiscrimants::Unit as u8);
    771 \end{rust}
    772 
    773 \subsection{Pointer casting}
    774 
    775 If the enumeration specifies a primitive representation, then the discriminant may be reliably accessed via unsafe pointer casting:
    776 \begin{rust}
    777 #[repr(u8)]
    778 enum Enum {
    779         Unit,
    780         Tuple(bool),
    781         Struct{a: bool},
    782 }
    783 
    784 impl Enum {
    785         fn discriminant(&self) -> u8 {
    786                 unsafe { *(self as *const Self as *const u8) }
    787         }
    788 }
    789 
    790 let unit_like = Enum::Unit;
    791 let tuple_like = Enum::Tuple(true);
    792 let struct_like = Enum::Struct{a: false};
    793 
    794 assert_eq!(0, unit_like.discriminant());
    795 assert_eq!(1, tuple_like.discriminant());
    796 assert_eq!(2, struct_like.discriminant());
    797 \end{rust}
    798 
    799 \subsection{Zero-variant enums}
    800 
    801 Enums with zero variants are known as zero-variant enums. As they have no valid values, they cannot be instantiated.
    802 \begin{rust}
    803 enum ZeroVariants {}
    804 \end{rust}
    805 Zero-variant enums are equivalent to the never type, but they cannot be coerced into other types.
    806 \begin{rust}
    807 let x: ZeroVariants = panic!();
    808 let y: u32 = x; // mismatched type error
    809 \end{rust}
    810 
    811 \subsection{Variant visibility}
    812 
    813 Enum variants syntactically allow a Visibility annotation, but this is rejected when the enum is validated. This allows items to be parsed with a unified syntax across different contexts where they are used.
    814 \begin{rust}
    815 macro_rules! mac_variant {
    816         ($vis:vis $name:ident) => {
    817                 enum $name {
    818                         $vis Unit,
    819 
    820                         $vis Tuple(u8, u16),
    821 
    822                         $vis Struct { f: u8 },
    823                 }
    824         }
    825 }
    826 
    827 // Empty `vis` is allowed.
    828 mac_variant! { E }
    829 
    830 // This is allowed, since it is removed before being validated.
    831 #[cfg(FALSE)]
    832 enum E {
    833         pub U,
    834         pub(crate) T(u8),
    835         pub(super) T { f: String }
    836 }
     649if week as isize == Week::Mon as isize ...
    837650\end{rust}
    838651
     
    12001013\lstnewenvironment{python}[1][]{\lstset{language=Python,escapechar=\$,moredelim=**[is][\color{red}]{@}{@},}\lstset{#1}}{}
    12011014
    1202 An @Enum@ is a set of symbolic names bound to unique values.
    1203 They are similar to global variables, but they offer a more useful @repr()@, grouping, type-safety, and a few other features.
    1204 
    1205 They are most useful when you have a variable that can take one of a limited selection of values. For example, the days of the week:
    1206 \begin{python}
    1207 >>> from enum import Enum
    1208 >>> class Weekday(Enum):
    1209 ...    MONDAY = 1
    1210 ...    TUESDAY = 2
    1211 ...    WEDNESDAY = 3
    1212 ...    THURSDAY = 4
    1213 ...    FRIDAY = 5
    1214 ...    SATURDAY = 6
    1215 ...    SUNDAY = 7
    1216 \end{python}
    1217 Or perhaps the RGB primary colors:
    1218 \begin{python}
    1219 >>> from enum import Enum
    1220 >>> class Color(Enum):
    1221 ...    RED = 1
    1222 ...    GREEN = 2
    1223 ...    BLUE = 3
    1224 \end{python}
    1225 As you can see, creating an @Enum@ is as simple as writing a class that inherits from @Enum@ itself.
    1226 
    1227 Note: Case of Enum Members
    1228 
    1229 Because Enums are used to represent constants, and to help avoid issues with name clashes between mixin-class methods/attributes and enum names, we strongly recommend using @UPPER_CASE@ names for members, and will be using that style in our examples.
     1015A Python enumeration is a set of symbolic names bound to \emph{unique} values.
     1016They are similar to global variables, but offer a more useful @repr()@, grouping, type-safety, and additional features.
     1017Enumerations inherits from the @Enum@ class, \eg:
     1018\begin{python}
     1019class Weekday(@Enum@): Mon = 1; Tue = 2; Wed = 3; Thu = 4; Fri = 5; Sat = 6; Sun = 7
     1020class RGB(@Enum@): Red = 1; Green = 2; Blue = 3
     1021\end{python}
    12301022
    12311023Depending on the nature of the enum a member's value may or may not be important, but either way that value can be used to get the corresponding member:
    12321024\begin{python}
    1233 >>> Weekday(3)
    1234 <Weekday.WEDNESDAY: 3>
     1025print( repr( Weekday( 3 ) ) )
     1026<Weekday.Wed: 3>
    12351027\end{python}
    12361028As you can see, the @repr()@ of a member shows the enum name, the member name, and the value.
    12371029The @str()@ of a member shows only the enum name and member name:
    12381030\begin{python}
    1239 print(Weekday.THURSDAY)
    1240 Weekday.THURSDAY
     1031print( str( Weekday.Thu ), Weekday.Thu )
     1032Weekday.Thu Weekday.Thu
    12411033\end{python}
    12421034The type of an enumeration member is the enum it belongs to:
    12431035\begin{python}
    1244 >>> type(Weekday.MONDAY)
     1036print( type( Weekday.Thu ) )
    12451037<enum 'Weekday'>
    1246 isinstance(Weekday.FRIDAY, Weekday)
     1038print( isinstance(Weekday.Fri, Weekday) )
    12471039True
    12481040\end{python}
    12491041Enum members have an attribute that contains just their name:
    12501042\begin{python}
    1251 >>> print(Weekday.TUESDAY.name)
     1043print(Weekday.TUESDAY.name)
    12521044TUESDAY
    12531045\end{python}
    12541046Likewise, they have an attribute for their value:
    12551047\begin{python}
    1256 >>> Weekday.WEDNESDAY.value
     1048Weekday.WEDNESDAY.value
    125710493
    12581050\end{python}
     1051
    12591052Unlike many languages that treat enumerations solely as name/value pairs, Python @Enum@s can have behavior added.
    12601053For example, @datetime.date@ has two methods for returning the weekday: @weekday()@ and @isoweekday()@.
     
    12621055Rather than keep track of that ourselves we can add a method to the @Weekday@ enum to extract the day from the date instance and return the matching enum member:
    12631056\begin{python}
     1057class Weekday(Enum): Mon = 1; Tue = 2; Wed = 3; Thu = 10; Fri = 15; Sat = 16; Sun = 17
    12641058$@$classmethod
    12651059def from_date(cls, date):
    1266     return cls(date.isoweekday())
    1267 \end{python}
    1268 The complete Weekday enum now looks like this:
    1269 \begin{python}
    1270 >>> class Weekday(Enum):
    1271 ...    MONDAY = 1
    1272 ...    TUESDAY = 2
    1273 ...    WEDNESDAY = 3
    1274 ...    THURSDAY = 4
    1275 ...    FRIDAY = 5
    1276 ...    SATURDAY = 6
    1277 ...    SUNDAY = 7
    1278 ...    #
    1279 ...    $@$classmethod
    1280 ...    def from_date(cls, date):
    1281 ...        return cls(date.isoweekday())
     1060        return cls(date.isoweekday())
    12821061\end{python}
    12831062Now we can find out what today is! Observe:
     
    12911070This Weekday enum is great if our variable only needs one day, but what if we need several? Maybe we're writing a function to plot chores during a week, and don't want to use a @list@ -- we could use a different type of @Enum@:
    12921071\begin{python}
    1293 >>> from enum import Flag
    1294 >>> class Weekday(Flag):
    1295 ...    MONDAY = 1
    1296 ...    TUESDAY = 2
    1297 ...    WEDNESDAY = 4
    1298 ...    THURSDAY = 8
    1299 ...    FRIDAY = 16
    1300 ...    SATURDAY = 32
    1301 ...    SUNDAY = 64
     1072from enum import Flag
     1073class WeekdayF(@Flag@): Mon = @1@; Tue = @2@; Wed = @4@; Thu = @8@; Fri = @16@; Sat = @32@; Sun = @64@
    13021074\end{python}
    13031075We've changed two things: we're inherited from @Flag@, and the values are all powers of 2.
    13041076
    1305 Just like the original @Weekday@ enum above, we can have a single selection:
    1306 \begin{python}
    1307 >>> first_week_day = Weekday.MONDAY
    1308 >>> first_week_day
    1309 <Weekday.MONDAY: 1>
    1310 \end{python}
    1311 But @Flag@ also allows us to combine several members into a single variable:
    1312 \begin{python}
    1313 >>> weekend = Weekday.SATURDAY | Weekday.SUNDAY
    1314 >>> weekend
    1315 <Weekday.SATURDAY|SUNDAY: 96>
     1077@Flag@ allows combining several members into a single variable:
     1078\begin{python}
     1079print( repr(WeekdayF.Sat | WeekdayF.Sun) )
     1080<WeekdayF.Sun|Sat: 96>
    13161081\end{python}
    13171082You can even iterate over a @Flag@ variable:
    13181083\begin{python}
    1319 >>> for day in weekend:
    1320 ...    print(day)
     1084for day in weekend:
     1085        print(day)
    13211086Weekday.SATURDAY
    13221087Weekday.SUNDAY
     
    13821147\subsection{Duplicating enum members and values}
    13831148
    1384 Having two enum members with the same name is invalid:
    1385 \begin{python}
    1386 >>> class Shape(Enum):
    1387 ...    SQUARE = 2
    1388 ...    SQUARE = 3
    1389 ...
    1390 Traceback (most recent call last):
    1391 ...
    1392 TypeError: 'SQUARE' already defined as 2
    1393 \end{python}
    1394 However, an enum member can have other names associated with it.
     1149An enum member can have other names associated with it.
    13951150Given two entries @A@ and @B@ with the same value (and @A@ defined first), @B@ is an alias for the member @A@.
    13961151By-value lookup of the value of @A@ will return the member @A@.
     
    13981153By-name lookup of @B@ will also return the member @A@:
    13991154\begin{python}
    1400 >>> class Shape(Enum):
    1401 ...    SQUARE = 2
    1402 ...    DIAMOND = 1
    1403 ...    CIRCLE = 3
    1404 ...    ALIAS_FOR_SQUARE = 2
    1405 ...
     1155class Shape(Enum): SQUARE = 2; DIAMOND = 1; CIRCLE = 3; ALIAS_FOR_SQUARE = 2
    14061156>>> Shape.SQUARE
    14071157<Shape.SQUARE: 2>
     
    14191169When this behavior isn't desired, you can use the @unique()@ decorator:
    14201170\begin{python}
    1421 >>> from enum import Enum, unique
    1422 >>> $@$unique
    1423 ... class Mistake(Enum):
    1424 ...     ONE = 1
    1425 ...     TWO = 2
    1426 ...     THREE = 3
    1427 ...     FOUR = 3
    1428 ...
    1429 Traceback (most recent call last):
    1430 ...
     1171from enum import Enum, unique
     1172$@$unique
     1173class DupVal(Enum): ONE = 1; TWO = 2; THREE = 3; FOUR = 3
    14311174ValueError: duplicate values found in <enum 'Mistake'>: FOUR -> THREE
    14321175\end{python}
     
    14361179If the exact value is unimportant you can use @auto@:
    14371180\begin{python}
    1438 >>> from enum import Enum, auto
    1439 >>> class Color(Enum):
    1440 ...     RED = auto()
    1441 ...     BLUE = auto()
    1442 ...     GREEN = auto()
    1443 ...
    1444 >>> [member.value for member in Color]
    1445 [1, 2, 3]
    1446 \end{python}
    1447 The values are chosen by \_generate\_next\_value\_(), which can be overridden:
     1181from enum import Enum, auto
     1182class RGBa(Enum): RED = auto(); BLUE = auto(); GREEN = auto()
     1183\end{python}
     1184(Like Golang @iota@.)
     1185The values are chosen by @_generate_next_value_()@, which can be overridden:
    14481186\begin{python}
    14491187>>> class AutoName(Enum):
     
    15821320\begin{python}
    15831321class EnumName([mix-in, ...,] [data-type,] base-enum):
    1584     pass
     1322        pass
    15851323\end{python}
    15861324Also, subclassing an enumeration is allowed only if the enumeration does not define any members.
     
    16991437\begin{python}
    17001438Enum(
    1701     value='NewEnumName',
    1702     names=<...>,
    1703     *,
    1704     module='...',
    1705     qualname='...',
    1706     type=<mixed-in class>,
    1707     start=1,
    1708     )
     1439        value='NewEnumName',
     1440        names=<...>,
     1441        *,
     1442        module='...',
     1443        qualname='...',
     1444        type=<mixed-in class>,
     1445        start=1,
     1446        )
    17091447\end{python}
    17101448\begin{itemize}
     
    19351673\begin{python}
    19361674class IntEnum(int, Enum):
    1937     pass
     1675        pass
    19381676\end{python}
    19391677This demonstrates how similar derived enumerations can be defined;
     
    20701808\begin{python}
    20711809def __bool__(self):
    2072     return bool(self.value)
     1810        return bool(self.value)
    20731811\end{python}
    20741812Plain @Enum@ classes always evaluate as @True@.
     
    24142152
    24152153If @__new__()@ or @__init__()@ is defined, the value of the enum member will be passed to those methods:
    2416 \begin{python}
    2417 >>> class Planet(Enum):
    2418 ...     MERCURY = (3.303e+23, 2.4397e6)
    2419 ...     VENUS   = (4.869e+24, 6.0518e6)
    2420 ...     EARTH   = (5.976e+24, 6.37814e6)
    2421 ...     MARS    = (6.421e+23, 3.3972e6)
    2422 ...     JUPITER = (1.9e+27,   7.1492e7)
    2423 ...     SATURN  = (5.688e+26, 6.0268e7)
    2424 ...     URANUS  = (8.686e+25, 2.5559e7)
    2425 ...     NEPTUNE = (1.024e+26, 2.4746e7)
    2426 ...     def __init__(self, mass, radius):
    2427 ...         self.mass = mass       # in kilograms
    2428 ...         self.radius = radius   # in meters
    2429 ...     $\@$property
    2430 ...     def surface_gravity(self):
    2431 ...         # universal gravitational constant  (m3 kg-1 s-2)
    2432 ...         G = 6.67300E-11
    2433 ...         return G * self.mass / (self.radius * self.radius)
    2434 ...
    2435 >>> Planet.EARTH.value
    2436 (5.976e+24, 6378140.0)
    2437 >>> Planet.EARTH.surface_gravity
    2438 9.802652743337129
    2439 \end{python}
     2154\begin{figure}
     2155\begin{python}
     2156from enum import Enum
     2157class Planet(Enum):
     2158        MERCURY = ( 3.303E23, 2.4397E6 )
     2159        VENUS       = ( 4.869E24, 6.0518E6 )
     2160        EARTH       = (5.976E24, 6.37814E6)
     2161        MARS         = (6.421E23, 3.3972E6)
     2162        JUPITER    = (1.9E27,   7.1492E7)
     2163        SATURN     = (5.688E26, 6.0268E7)
     2164        URANUS    = (8.686E25, 2.5559E7)
     2165        NEPTUNE  = (1.024E26, 2.4746E7)
     2166        def __init__( self, mass, radius ):
     2167                self.mass = mass                # in kilograms
     2168                self.radius = radius    # in meters
     2169        def surface_gravity( self ):
     2170                # universal gravitational constant  (m3 kg-1 s-2)
     2171                G = 6.67300E-11
     2172                return G * self.mass / (self.radius * self.radius)
     2173for p in Planet:
     2174        print( f"{p.name}: {p.value}" )
     2175
     2176MERCURY: (3.303e+23, 2439700.0)
     2177VENUS: (4.869e+24, 6051800.0)
     2178EARTH: (5.976e+24, 6378140.0)
     2179MARS: (6.421e+23, 3397200.0)
     2180JUPITER: (1.9e+27, 71492000.0)
     2181SATURN: (5.688e+26, 60268000.0)
     2182URANUS: (8.686e+25, 25559000.0)
     2183NEPTUNE: (1.024e+26, 24746000.0)
     2184\end{python}
     2185\caption{Python Planet Example}
     2186\label{f:PythonPlanetExample}
     2187\end{figure}
     2188
    24402189
    24412190\subsection{TimePeriod}
     
    24642213\section{OCaml}
    24652214\lstnewenvironment{ocaml}[1][]{\lstset{language=OCaml,escapechar=\$,moredelim=**[is][\color{red}]{@}{@},}\lstset{#1}}{}
     2215
     2216% https://ocaml.org/docs/basic-data-types#enumerated-data-types
    24662217
    24672218OCaml provides a variant (union) type, where multiple heterogeneously-typed objects share the same storage.
     
    25532304With valediction,
    25542305  - Gregor Richards
     2306
     2307
     2308Date: Thu, 14 Mar 2024 21:45:52 -0400
     2309Subject: Re: OCaml "enums" do come with ordering
     2310To: "Peter A. Buhr" <pabuhr@uwaterloo.ca>
     2311From: Gregor Richards <gregor.richards@uwaterloo.ca>
     2312
     2313On 3/14/24 21:30, Peter A. Buhr wrote:
     2314> I've marked 3 places with your name to shows places with enum ordering.
     2315>
     2316> type weekday = Mon | Tue | Wed | Thu | Fri | Sat | Sun
     2317> let day : weekday = Mon
     2318> let take_class( d : weekday ) =
     2319>       if d <= Fri then                                (* Gregor *)
     2320>               Printf.printf "weekday\n"
     2321>       else if d >= Sat then                   (* Gregor *)
     2322>               Printf.printf "weekend\n";
     2323>       match d with
     2324>               Mon | Wed -> Printf.printf "CS442\n" |
     2325>               Tue | Thu -> Printf.printf "CS343\n" |
     2326>               Fri -> Printf.printf "Tutorial\n" |
     2327>               _ -> Printf.printf "Take a break\n"
     2328>
     2329> let _ = take_class( Mon ); take_class( Sat );
     2330>
     2331> type colour = Red | Green of string | Blue of int * float
     2332> let c = Red
     2333> let _ = match c with Red -> Printf.printf "Red, "
     2334> let c = Green( "abc" )
     2335> let _ = match c with Green g -> Printf.printf "%s, " g
     2336> let c = Blue( 1, 1.5 )
     2337> let _ = match c with Blue( i, f ) -> Printf.printf "%d %g\n" i f
     2338>
     2339> let check_colour(c: colour): string =
     2340>       if c < Green( "xyz" ) then              (* Gregor *)
     2341>               Printf.printf "green\n";
     2342>       match c with
     2343>               Red -> "Red" |
     2344>               Green g -> g |
     2345>               Blue(i, f) -> string_of_int i ^ string_of_float f
     2346> let _ = check_colour( Red ); check_colour( Green( "xyz" ) );
     2347>
     2348> type stringList = Empty | Pair of string * stringList
     2349> let rec len_of_string_list(l: stringList): int =
     2350>       match l with
     2351>               Empty -> 0 |
     2352>               Pair(_ , r) -> 1 + len_of_string_list r
     2353>
     2354> let _ = for i = 1 to 10 do
     2355>       Printf.printf "%d, " i
     2356> done
     2357>
     2358> (* Local Variables: *)
     2359> (* tab-width: 4 *)
     2360> (* compile-command: "ocaml test.ml" *)
     2361> (* End: *)
     2362
     2363My functional-language familiarity is far more with Haskell than OCaml.  I
     2364mostly view OCaml through a lens of "it's Haskell but with cheating".  Haskell
     2365"enums" (ADTs) aren't ordered unless you specifically and manually put them in
     2366the Ord typeclass by defining the comparators.  Apparently, OCaml has some
     2367other rule, which I would guess is something like "sort by tag then by order of
     2368parameter". Having a default behavior for comparators is *bizarre*; my guess
     2369would be that it gained this behavior in its flirtation with object
     2370orientation, but that's just a guess (and irrelevant).
     2371
     2372This gives a total order, but not enumerability (which would still be
     2373effectively impossible or even meaningless since enums are just a special case
     2374of ADTs).
     2375
     2376With valediction,
     2377  - Gregor Richards
     2378
     2379Date: Wed, 20 Mar 2024 18:16:44 -0400
     2380Subject: Re:
     2381To: "Peter A. Buhr" <pabuhr@uwaterloo.ca>
     2382From: Gregor Richards <gregor.richards@uwaterloo.ca>
     2383
     2384
     2385On 3/20/24 17:26, Peter A. Buhr wrote:
     2386> Gregor, everyone at this end would like a definition of "enumerability". Can
     2387> you formulate one?
     2388
     2389According to the OED (emphasis added to the meaning I'm after):
     2390
     2391enumerate (verb, transitive). To count, ascertain the number of; **more
     2392usually, to mention (a number of things or persons) separately, as if for the
     2393purpose of counting**; to specify as in a list or catalogue.
     2394
     2395With C enums, if you know the lowest and highest value, you can simply loop
     2396over them in a for loop (this is, of course, why so many enums come with an
     2397ENUM_WHATEVER_LAST value). But, I would be hesitant to use the word "loop" to
     2398describe enumerability, since in functional languages, you would recurse for
     2399such a purpose.
     2400
     2401In Haskell, in order to do something with every member of an "enumeration", you
     2402would have to explicitly list them all. The type system will help a bit since
     2403it knows if you haven't listed them all, but you would have to statically have
     2404every element in the enumeration.  If somebody added new elements to the
     2405enumeration later, your code to enumerate over them would no longer work
     2406correctly, because you can't simply say "for each member of this enumeration do
     2407X". In Haskell that's because there aren't actually enumerations; what they use
     2408as enumerations are a degenerate form of algebraic datatypes, and ADTs are
     2409certainly not enumerable. In OCaml, you've demonstrated that they impose
     2410comparability, but I would still assume that you can't make a loop over every
     2411member of an enumeration. (But, who knows!)
     2412
     2413Since that's literally what "enumerate" means, it seems like a rather important
     2414property for enumerations to have ;)
     2415
     2416With valediction,
     2417  - Gregor Richards
     2418
     2419
     2420From: Andrew James Beach <ajbeach@uwaterloo.ca>
     2421To: Gregor Richards <gregor.richards@uwaterloo.ca>, Peter Buhr <pabuhr@uwaterloo.ca>
     2422CC: Michael Leslie Brooks <mlbrooks@uwaterloo.ca>, Fangren Yu <f37yu@uwaterloo.ca>,
     2423    Jiada Liang <j82liang@uwaterloo.ca>
     2424Subject: Re: Re:
     2425Date: Thu, 21 Mar 2024 14:26:36 +0000
     2426
     2427Does this mean that not all enum declarations in C create enumerations? If you
     2428declare an enumeration like:
     2429
     2430enum Example {
     2431    Label,
     2432    Name = 10,
     2433    Tag = 3,
     2434};
     2435
     2436I don't think there is any way to enumerate (iterate, loop, recurse) over these
     2437values without listing all of them.
     2438
     2439
     2440Date: Thu, 21 Mar 2024 10:31:49 -0400
     2441Subject: Re:
     2442To: Andrew James Beach <ajbeach@uwaterloo.ca>, Peter Buhr <pabuhr@uwaterloo.ca>
     2443CC: Michael Leslie Brooks <mlbrooks@uwaterloo.ca>, Fangren Yu <f37yu@uwaterloo.ca>,
     2444    Jiada Liang <j82liang@uwaterloo.ca>
     2445From: Gregor Richards <gregor.richards@uwaterloo.ca>
     2446
     2447I consider this conclusion reasonable. C enums can be nothing more than const
     2448ints, and if used in that way, I personally wouldn't consider them as
     2449enumerations in any meaningful sense, particularly since the type checker
     2450essentially does nothing for you there. Then they're a way of writing consts
     2451repeatedly with some textual indicator that these definitions are related; more
     2452namespace, less enum.
     2453
     2454When somebody writes bitfield members as an enum, is that *really* an
     2455enumeration, or just a use of the syntax for enums to keep related definitions
     2456together?
     2457
     2458With valediction,
     2459  - Gregor Richards
    25552460\end{comment}
    25562461
     
    25582463\section{Comparison}
    25592464
    2560 \begin{tabular}{r|ccccccccc}
    2561 feat. / lang. & Pascal  & Ada   & \Csharp       & OCaml & Java  & Modula-3      & Rust  & Swift & Python        \\
     2465\VRef[Table]{t:FeatureLanguageComparison} shows a comparison of enumeration features and programming languages.
     2466The features are high level and may not capture nuances within a particular language
     2467The @const@ feature is simple macros substitution and not a typed enumeration.
     2468
     2469\begin{table}
     2470\caption{Enumeration Feature / Language Comparison}
     2471\label{t:FeatureLanguageComparison}
     2472\small
     2473\setlength{\tabcolsep}{3pt}
     2474\newcommand{\CM}{\checkmark}
     2475\begin{tabular}{r|c|c|c|c|c|c|c|c|c|c|c|c|c}
     2476                                &Pascal & Ada   &\Csharp& OCaml & Java  &Modula-3&Golang& Rust  & Swift & Python& C             & \CC   & \CFA  \\
    25622477\hline
    2563 pure            &                       &               &                       &               &               &                       &               &               &                       \\
    2564 ordered         &                       &               &                       &               &               &                       &               &               &                       \\
    2565 setable         &                       &               &                       &               &               &                       &               &               &                       \\
    2566 auto-init       &                       &               &                       &               &               &                       &               &               &                       \\
    2567 scoped          &                       &               &                       &               &               &                       &               &               &                       \\
    2568 typed           &                       &               &                       &               &               &                       &               &               &                       \\
    2569 switch          &                       &               &                       &               &               &                       &               &               &                       \\
    2570 loop            &                       &               &                       &               &               &                       &               &               &                       \\
    2571 array           &                       &               &                       &               &               &                       &               &               &                       \\
     2478@const@                 & \CM   &               &               &               &               &               & \CM   &               &               &               &               & \CM   &               \\
     2479\hline
     2480\hline
     2481pure                    &               &               &               &               &               &               &               &               &               &               &               &               & \CM   \\
     2482\hline
     2483typed                   &               &               &               &               &               &               &               &               &               &               & @int@ & integral      & @T@   \\
     2484\hline
     2485safe                    &               &               &               &               &               &               &               &               &               &               &               & \CM   & \CM   \\
     2486\hline
     2487ordered                 &               &               &               &               &               &               &               &               &               &               & \CM   & \CM   & \CM   \\
     2488\hline
     2489dup. values             &               &               &               &               &               &               &               &               &               & alias & \CM   & \CM   & \CM   \\
     2490\hline
     2491setable                 &               &               &               &               &               &               &               &               &               &               & \CM   & \CM   & \CM   \\
     2492\hline
     2493auto-init               &               &               &               &               &               &               &               &               &               &               & \CM   & \CM   & \CM   \\
     2494\hline
     2495(un)scoped              &               &               &               &               &               &               &               &               &               &               & U             & U/S   & U/S   \\
     2496\hline
     2497overload                &               & \CM   &               &               &               &               &               &               &               &               &               & \CM   & \CM   \\
     2498\hline
     2499switch                  &               &               &               &               &               &               &               &               &               &               & \CM   & \CM   & \CM   \\
     2500\hline
     2501loop                    &               &               &               &               &               &               &               &               &               &               &               &               & \CM   \\
     2502\hline
     2503array                   &               &               &               &               &               &               &               &               &               &               & \CM   &               & \CM   \\
     2504\hline
     2505subtype                 &               &               &               &               &               &               &               &               &               &               &               &               & \CM   \\
     2506\hline
     2507inheritance             &               &               &               &               &               &               &               &               &               &               &               &               & \CM   \\
    25722508\end{tabular}
     2509\end{table}
Note: See TracChangeset for help on using the changeset viewer.