Changeset 7d9a805b
- Timestamp:
- Mar 21, 2024, 9:34:28 PM (5 months ago)
- Branches:
- master
- Children:
- 6394ac6
- Parents:
- 0139351
- Location:
- doc/theses/jiada_liang_MMath
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/theses/jiada_liang_MMath/CFAenum.tex
r0139351 r7d9a805b 1 \chapter{\CFA -Style Enum}2 3 4 \CFA supports C -Styleenumeration using the same syntax and semantics for backwards compatibility.1 \chapter{\CFA Enumeration} 2 3 4 \CFA supports C enumeration using the same syntax and semantics for backwards compatibility. 5 5 \CFA also extends C-Style enumeration by adding a number of new features that bring enumerations inline with other modern programming languages. 6 6 … … 16 16 Finally, qualification is provided to disambiguate any ambiguous situations. 17 17 \begin{cfa} 18 enum C1 { First, Second, Third, Fourth };19 enum C2 { @Fourth@, @Third@, @Second@, @First@ };20 C1 p() { return Third; } $\C{// correctly resolved duplicate names}$21 C2 p() { return Fourth; }18 enum E1 { First, Second, Third, Fourth }; 19 enum E2 { @Fourth@, @Third@, @Second@, @First@ }; 20 E1 p() { return Third; } $\C{// correctly resolved duplicate names}$ 21 E2 p() { return Fourth; } 22 22 void foo() { 23 C1 e1 = First; C2 e2 = First;23 E1 e1 = First; E2 e2 = First; 24 24 e1 = Second; e2 = Second; 25 25 e1 = p(); e2 = p(); $\C{// correctly resolved function call}$ 26 int i = @C1.@First + @C2.@First; $\C{// ambiguous without qualification}$ 27 } 28 \end{cfa} 29 \CFA overloading allows programmers to use the most meaningful names without fear of unresolvable clashes from included files, which are correctable with qualification. 26 int i = @E1.@First + @E2.@First; $\C{// disambiguate with qualification}$ 27 int j = @(E1)@First + @(E2)@First; $\C{// disambiguate with cast}$ 28 } 29 \end{cfa} 30 \CFA overloading allows programmers to use the most meaningful names without fear of name clashes from include files. 31 Either the type system implicitly disambiguates or the programmer explicitly disambiguates using qualification or casting. 30 32 31 33 … … 34 36 An enumeration can be scoped, so the enumerator constants are not projected into the enclosing scope, using @'!'@. 35 37 \begin{cfa} 36 enum Weekday @!@ { /* as above */};37 enum ( char * ) Names @!@ { /* as above */};38 enum Weekday @!@ { Mon, Tue, Wed, Thu = 10, Fri, Sat, Sun }; 39 enum RGB @!@ { Red, Green, Blue }; 38 40 \end{cfa} 39 41 Now the enumerators \emph{must} be qualified with the associated enumeration. 40 42 \begin{cfa} 41 Weekday weekday = @Weekday@.Monday; 42 Names names = @Names.@Fred; 43 names = @Names.@Jane; 43 Weekday weekday = @Weekday@.Mon; 44 weekday = @Weekday@.Sat; 45 RGB rgb = RGB.Red; 46 rgb = RGB.Blue; 44 47 \end{cfa} 45 48 It 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}). 46 49 \begin{cfa} 47 Weekday weekday; 48 with ( @Weekday@, @Names@ ) { $\C{// type names}$ 49 Names names = @Fred@; 50 names = @Jane@; 51 weekday = Saturday; 52 } 53 \end{cfa} 54 As in Section~\ref{s:EnumeratorNameResolution}, opening multiple unscoped enumerations can result in duplicate enumeration names, but \CFA type resolution and falling back to explicit qualification handles name resolution. 50 with ( @Weekday@, @RGB@ ) { $\C{// type names}$ 51 weekday = @Sun@; $\C{// no qualification}$ 52 rgb = @Green@; 53 } 54 \end{cfa} 55 As in Section~\ref{s:EnumeratorNameResolution}, opening multiple unscoped enumerations can result in duplicate enumeration names, but \CFA implicit type resolution and explicit qualification/casting handles name resolution. 55 56 56 57 \section{Enumerator Typing} … … 80 81 \begin{cfa} 81 82 // integral 82 enum( @char@ ) Currency { Dollar = '$\textdollar$', Euro = '$\texteuro$', Pound = '$\textsterling$'};83 enum( @char@ ) Currency { Dollar = '$\textdollar$', Cent = '$\textcent$', Yen = '$\textyen$', Pound = '$\textsterling$', Euro = 'E' }; 83 84 enum( @signed char@ ) srgb { Red = -1, Green = 0, Blue = 1 }; 84 85 enum( @long long int@ ) BigNum { X = 123_456_789_012_345, Y = 345_012_789_456_123 }; … … 87 88 enum( @_Complex@ ) Plane { X = 1.5+3.4i, Y = 7+3i, Z = 0+0.5i }; 88 89 // pointer 89 enum( @c har *@ ) Names{ Fred = "FRED", Mary = "MARY", Jane = "JANE" };90 enum( @const char *@ ) Name { Fred = "FRED", Mary = "MARY", Jane = "JANE" }; 90 91 int i, j, k; 91 92 enum( @int *@ ) ptr { I = &i, J = &j, K = &k }; … … 98 99 // aggregate 99 100 struct Person { char * name; int age, height; }; 100 @***@enum( @Person@ ) friends { @Liz@ = { "ELIZABETH", 22, 170 }, @Beth@ = Liz, Jon = { "JONATHAN", 35, 190 } }; 101 @***@enum( @Person@ ) friends { @Liz@ = { "ELIZABETH", 22, 170 }, @Beth@ = Liz, 102 Jon = { "JONATHAN", 35, 190 } }; 101 103 \end{cfa} 102 104 \caption{Enumerator Typing} … … 140 142 \begin{cfa} 141 143 enum() Mode { O_RDONLY, O_WRONLY, O_CREAT, O_TRUNC, O_APPEND }; 142 @***@Mode iomode = O_RDONLY;143 bool b = iomode == O_RDONLY || iomode < O_APPEND; 144 int i = iomode; $\C{\color{red}// disallowed}$144 Mode iomode = O_RDONLY; 145 bool b = iomode == O_RDONLY || iomode < O_APPEND; $\C{// ordering}$ 146 @***@@int i = iomode;@ $\C{// disallow conversion to int}$ 145 147 \end{cfa} 146 148 … … 149 151 If follows from enumerator typing that the enumerator type can be another enumerator. 150 152 \begin{cfa} 151 enum( @char@ ) Currency { Dollar = '$\textdollar$', Euro = '$\texteuro$', Pound = '$\textsterling$'};152 enum( @Currency@ ) Europe { Euro = Currency.Euro, Pound = Currency.Pound }; // intersection153 enum( @char@ ) Currency { Dollar = '$\textdollar$', Cent = '$\textcent$', Yen = '$\textyen$', Pound = '$\textsterling$', Euro = 'E' }; 154 enum( Currency ) Europe { Euro = Currency.Euro, Pound = Currency.Pound }; 153 155 enum( char ) Letter { A = 'A', B = 'B', C = 'C', ..., Z = 'Z' }; 154 156 enum( @Letter@ ) Greek { Alph = A, Beta = B, ..., Zeta = Z }; // intersection … … 158 160 \begin{cfa} 159 161 Letter letter = A; 160 @***@Greak greek = Beta;161 letter = Beta; $\C{// allowed, letter== B}$162 greek = A; $\C{\color{red}// disallowed}$162 Greak greek = Beta; 163 letter = Beta; $\C{// allowed, greek == B}$ 164 @greek = A;@ $\C{// disallowed}$ 163 165 \end{cfa} 164 166 … … 277 279 p(variable_d); // 3 278 280 \end{cfa} 281 282 283 \section{Planet Example} 284 285 \VRef[Figure]{f:PlanetExample} shows an archetypal enumeration example illustrating all of the \CFA enumeration features. 286 Enumeration @Planet@ is a typed enumeration of type @MR@. 287 Each of the planet enumerators is initialized to a specific mass/radius, @MR@, value. 288 The unnamed enumeration projects the gravitational-constant enumerator @G@. 289 The program main iterates through the planets computing the weight on each planet for a given earth weight. 290 291 \begin{figure} 292 \begin{cfa} 293 struct MR { double mass, radius; }; 294 enum( MR ) Planet { 295 // mass radius 296 MERCURY = { 3.303_E23, 2.4397_E6 }, 297 VENUS = { 4.869_E24, 6.0518_E6 }, 298 EARTH = { 5.976_E24, 6.3781_E6 }, 299 MARS = { 6.421_E23, 3.3972_E6 }, 300 JUPITER = { 1.898_E27, 7.1492_E7 }, 301 SATURN = { 5.688_E26, 6.0268_E7 }, 302 URANUS = { 8.686_E25, 2.5559_E7 }, 303 NEPTUNE = { 1.024_E26, 2.4746_E7 }, 304 }; 305 enum( double ) { G = 6.6743E-11 }; // universal gravitational constant (m3 kg-1 s-2) 306 307 static double surfaceGravity( Planet p ) with( p ) { 308 return G * mass / ( radius * radius ); 309 } 310 static double surfaceWeight( Planet p, double otherMass ) { 311 return otherMass * surfaceGravity( p ); 312 } 313 int main( int argc, char * argv[] ) { 314 if ( argc != 2 ) exit | "Usage: " | argv[0] | "earth-weight"; 315 double earthWeight = convert( argv[1] ); 316 double mass = earthWeight / surfaceGravity( EARTH ); 317 for ( p; Planet ) { 318 sout | "Your weight on" | labelE(p) | "is" | surfaceWeight( p, mass ); 319 } 320 } 321 \end{cfa} 322 \caption{Planet Example} 323 \label{f:PlanetExample} 324 \end{figure} -
doc/theses/jiada_liang_MMath/background.tex
r0139351 r7d9a805b 1 1 \chapter{Background} 2 \lstnewenvironment{clang}[1][]{\lstset{language=[ANSI]C,escapechar=\$,moredelim=**[is][\color{red}]{@}{@},}\lstset{#1}}{} 3 4 \CFA is a backwards-compatible extension of the C programming language. 5 Therefore, it must support C-style enumerations and any enumeration extensions must be intuitive to C programmers both in syntax and semantics. 6 7 It is common for C programmers to ``believe'' there are three equivalent forms of named constants. 8 \begin{clang} 9 #define Mon 0 10 static const int Mon = 0; 11 enum { Mon }; 12 \end{clang} 13 \begin{enumerate}[leftmargin=*] 14 \item 15 For @#define@, the programmer has to explicitly manage the constant name and value. 16 Furthermore, these C preprocessor macro names are outside of the C type-system, and hence cannot be overloaded, and can incorrectly change random text in a program. 17 \item 18 The 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{ 19 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 operands of assembler instructions, and occupy storage. 20 \begin{clang} 21 $\$$ nm test.o 22 0000000000000018 r Mon 23 \end{clang} 24 \item 25 Only the @enum@ form is managed by the compiler, is part of the language type-system, and works in all C constant-expression locations. 26 \end{enumerate} 2 27 3 28 4 \section{C -Style Enum}29 \section{C \lstinline{const}} 5 30 6 The C-Style enumeration has the following syntax and semantics. 7 \begin{cfa} 8 enum Weekday { Monday, Tuesday, Wednesday, Thursday@ = 10@, Friday, Saturday, Sunday }; 9 \end{cfa} 31 As noted, C has the equivalent of Pascal typed @const@ declarations \see{\VRef{s:Pascal}}, with static and dynamic initialization. 32 \begin{clang} 33 static const int one = 0 + 1; $\C{// static intialization}$ 34 static const void * NIL = NULL; 35 static const double PI = 3.14159; 36 static const char Plus = '+'; 37 static const char * Fred = "Fred"; 38 static const int Mon = 0, Tue = Mon + 1, Wed = Tue + 1, Thu = Wed + 1, Fri = Thu + 1, 39 Sat = Fri + 1, Sun = Sat + 1; 40 void foo() { 41 const int r = random(); $\C{// dynamic intialization}$ 42 int sa[Sun]; $\C{// VLA, local scope only}$ 43 } 44 \end{clang} 45 Statically initialized identifiers may appear in any constant-expression context, \eg @case@. 46 Dynamically initialized identifiers may appear as array dimensions in @g++@, which allows variable-sized arrays. 47 48 49 \section{C Enumeration} 50 51 The C enumeration has the following syntax and semantics. 52 \begin{clang} 53 enum Weekday { Mon, Tue, Wed, Thu@ = 10@, Fri, Sat, Sun, }; 54 \end{clang} 10 55 Enumerators without an explicitly designated constant value are \Newterm{auto-initialized} by the compiler: from left to right, starting at zero or the next explicitly initialized constant, incrementing by @1@. 11 For example, @Mon day@ to @Wednesday@ are implicitly assigned with constants @0@--@2@, @Thursday@ is explicitly set to constant @10@, and @Friday@ to @Sunday@ are implicitly assigned with constants @11@--@13@.56 For example, @Mon@ to @Wed@ are implicitly assigned with constants @0@--@2@, @Thu@ is explicitly set to constant @10@, and @Fri@ to @Sun@ are implicitly assigned with constants @11@--@13@. 12 57 Initialization may occur in any order. 13 \begin{c fa}14 enum Weekday { Thu rsday@ = 10@, Friday, Saturday, Sunday, Monday@ = 0@, Tuesday, Wednesday};15 \end{c fa}58 \begin{clang} 59 enum Weekday { Thu@ = 10@, Fri, Sat, Sun, Mon@ = 0@, Tue, Wed }; 60 \end{clang} 16 61 Note, the comma in the enumerator list can be a terminator or a separator, allowing the list to end with a dangling comma. 17 \begin{c fa}62 \begin{clang} 18 63 enum Weekday { 19 Thu rsday = 10, Friday, Saturday, Sunday,20 Mon day = 0, Tuesday, Wednesday@,@ // terminating comma64 Thu = 10, Fri, Sat, Sun, 65 Mon = 0, Tue, Wed@,@ // terminating comma 21 66 }; 22 \end{c fa}67 \end{clang} 23 68 This feature allow enumerator lines to be interchanged without moving a comma.\footnote{ 24 69 A terminating comma appears in other C syntax, \eg the initializer list.} … … 28 73 In practice, since integral constants are used, which have type @int@ (unless qualified with a size suffix), C uses @int@ as the underlying type for enumeration variables. 29 74 Finally, there is an implicit bidirectional conversion between an enumeration and its integral type. 30 \begin{c fa}75 \begin{clang} 31 76 { 32 77 enum Weekday { /* as above */ }; $\C{// enumerators implicitly projected into local scope}$ 33 Weekday weekday = Mon day;$\C{// weekday == 0}$34 weekday = Fri day;$\C{// weekday == 11}$35 int i = Sun day; $\C{// implicit conversion to int, i == 13}$78 Weekday weekday = Mon; $\C{// weekday == 0}$ 79 weekday = Fri; $\C{// weekday == 11}$ 80 int i = Sun; $\C{// implicit conversion to int, i == 13}$ 36 81 weekday = 10000; $\C{// UNDEFINED! implicit conversion to Weekday}$ 37 82 } 38 int j = Wed nesday; $\C{// ERROR! Wednesdayis not declared in this scope}$39 \end{c fa}83 int j = Wed; $\C{// ERROR! Wed is not declared in this scope}$ 84 \end{clang} 40 85 The implicit conversion from @int@ to an enumeration type is an unnecessary source of error. 41 42 It is common for C programmers to ``believe'' there are 3 equivalent forms of constant enumeration.43 \begin{cfa}44 #define Monday 045 static const int Monday = 0;46 enum { Monday };47 \end{cfa}48 For @#define@, the programmer has to play compiler and explicitly manage the enumeration values;49 furthermore, these are independent constants outside of any language type mechanism.50 The same explicit management is true for @const@ declarations, and the @const@ variable cannot appear in constant-expression locations, like @case@ labels, array dimensions,\footnote{51 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++}.} and immediate operands of assembler instructions.52 Only the @enum@ form is managed by the compiler, is part of the language type-system, and works in all C constant-expression locations. -
doc/theses/jiada_liang_MMath/implementation.tex
r0139351 r7d9a805b 548 548 \begin{cfa} 549 549 enum(int) Weekday { 550 Mon day=10, Tuesday, ...550 Mon = 10, Tue, ... 551 551 }; 552 552 -
doc/theses/jiada_liang_MMath/intro.tex
r0139351 r7d9a805b 4 4 Naming is also commonly used to represent many other numerical phenomenon, such as days of the week, months of a year, floors of a building (basement), specific times (noon, New Years). 5 5 Many programming languages capture this important software engineering capability through a mechanism called an \Newterm{enumeration}. 6 An enumeration is similar to other programming-language types by providing a set of constrained values, but adds the ability to name \emph{all} the values in itsset.6 An enumeration is similar to other programming-language types by providing a set of constrained values, but adds the ability to name \emph{all} the values in the set. 7 7 Note, all enumeration names must be unique but different names can represent the same value (eight note, quaver), which are synonyms. 8 8 … … 11 11 12 12 Fundamentally, all enumeration systems have an \Newterm{enumeration} type with an associated set of \Newterm{enumerator} names. 13 An enumeration has three universal attributes, \Newterm{ position}, \Newterm{label}, and \Newterm{value}, as shown by this representative enumeration, where position and value can be different.13 An enumeration has three universal attributes, \Newterm{label}, \Newterm{position}, and \Newterm{value}, as shown by this representative enumeration, where position and value can be different. 14 14 \begin{cquote} 15 15 \small\sf\setlength{\tabcolsep}{3pt} … … 17 17 \it\color{red}enumeration & \multicolumn{7}{c}{\it\color{red}enumerators} \\ 18 18 $\downarrow$\hspace*{25pt} & \multicolumn{7}{c}{$\downarrow$} \\ 19 @enum@ Weekday \{ & Mon day, & Tuesday, & Wednesday, & Thursday,& Friday, & Saturday, & Sunday \};\\20 \it\color{red} position & 0 & 1 & 2 & 3 & 4 & 5 & 6\\21 \it\color{red} label & Monday & Tuesday & Wednesday & Thursday & Friday & Saturday & Sunday\\22 \it\color{red}value & 0 & 1 & 2 & 3 & 4& 5 & 619 @enum@ Weekday \{ & Mon, & Tue, & Wed, & Thu, & Fri, & Sat, & Sun \}; \\ 20 \it\color{red}label & Mon & Tue & Wed & Thu & Fri & Sat & Sun \\ 21 \it\color{red}position & 0 & 1 & 2 & 3 & 4 & 5 & 6 \\ 22 \it\color{red}value & 0 & 1 & 2 & 3 & 4 & 5 & 6 23 23 \end{tabular} 24 24 \end{cquote} 25 Here, the \Newterm{enumeration} @Weekday@ defines the ordered \Newterm{enumerator}s @Monday@, @Tuesday@, @Wednesday@, @Thursday@, @Friday@, @Saturday@ and @Sunday@. 26 By convention, the successor of @Tuesday@ is @Monday@ and the predecessor of @Tuesday@ is @Wednesday@, independent of the associated enumerator constant values. 27 Because an enumerator is a constant, it cannot appear in a mutable context, \eg @Mon = Sun@ is meaningless, and an enumerator has no address, it is an \Newterm{rvalue}\footnote{ 28 The term rvalue defines an expression that can only appear on the right-hand side of an assignment.}. 25 Here, the \Newterm{enumeration} @Weekday@ defines the ordered \Newterm{enumerator}s @Mon@, @Tue@, @Wed@, @Thu@, @Fri@, @Sat@ and @Sun@. 26 By convention, the successor of @Tue@ is @Mon@ and the predecessor of @Tue@ is @Wed@, independent of the associated enumerator constant values, implying an ordering among the enumerators. 27 As well, the value can be explicitly set so it is different from the position. 28 Because an enumerator is a constant, it cannot appear in a mutable context, \eg @Mon = Sun@ is meaningless, and an enumerator has no address, \ie it is an \Newterm{rvalue}\footnote{ 29 The term rvalue defines an expression that can only appear on the right-hand side of an assignment expression.}. 30 31 On the surface, enumerations seem like a simple type. 32 However, when extended with features available in other language types, enumerations become a complex. 33 34 The goal of this work is to to extend the simple and unsafe enumeration type in the C programming-language into a sophisticated and safe type in the \CFA programming-language, while maintain backwards compatibility with C. 29 35 30 36 \section{Contributions} 37 -
doc/theses/jiada_liang_MMath/relatedwork.tex
r0139351 r7d9a805b 2 2 \label{s:RelatedWork} 3 3 4 \begin{comment} 4 5 An algebraic data type (ADT) can be viewed as a recursive sum of product types. 5 6 A sum type lists values as members. … … 15 16 Enumerated 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. 16 17 Values of algebraic types are access by subscripting, field qualification, or type (pattern) matching. 18 \end{comment} 17 19 18 20 Enumeration 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}. … … 20 22 21 23 \section{Pascal} 24 \label{s:Pascal} 22 25 \lstnewenvironment{pascal}[1][]{\lstset{language=pascal,escapechar=\$,moredelim=**[is][\color{red}]{@}{@},}\lstset{#1}}{} 23 26 … … 27 30 PI = 3.14159; Plus = '+'; Fred = 'Fred'; 28 31 \end{pascal} 29 Here, there is noenumeration because there is no specific type (pseudo enumeration).32 This mechanism is not an enumeration because there is no specific type (pseudo enumeration). 30 33 Hence, there is no notion of a (possibly ordered) set, modulo the \lstinline[language=pascal]{set of} type. 31 34 The type of each constant name (enumerator) is inferred from the constant-expression type. … … 81 84 with Ada.Text_IO; use Ada.Text_IO; 82 85 procedure test is 83 84 85 86 87 88 89 90 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; 91 94 begin 92 93 94 95 @Red@( Blue ); -- RGB 96 @Red@( Yellow ); -- Traffic_Light 97 @Red@( @RGB'(Red)@ ); -- ambiguous without cast 95 98 end test; 96 99 \end{ada} … … 224 227 \lstnewenvironment{c++}[1][]{\lstset{language=[GNU]C++,escapechar=\$,moredelim=**[is][\color{red}]{@}{@},}\lstset{#1}}{} 225 228 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++} 231 const auto one = 0 + 1; $\C{// static intialization}$ 232 const auto NULL = nullptr; 233 const auto PI = 3.14159; 234 const auto Plus = '+'; 235 const auto Fred = "Fred"; 236 const auto Mon = 0, Tue = Mon + 1, Wed = Tue + 1, Thu = Wed + 1, Fri = Thu + 1, 237 Sat = Fri + 1, Sun = Sat + 1; 238 int sa[Sun]; 239 const auto r = random(); $\C{// dynamic intialization}$ 240 int da[r]; $\C{// VLA}$ 241 \end{c++} 242 Statically initialized identifiers may appear in any constant-expression context, \eg @case@. 243 Dynamically intialized identifiers may appear as array dimensions in @g++@, which allows variable-sized arrays. 244 Interestingly, global \CC @const@ declarations are implicitly marked @static@ (@r@ rather than @R@). 245 \begin{c++} 246 $\$$ nm test.o 247 0000000000000018 @r@ Mon 248 \end{c++} 249 250 \CC enumeration is largely backwards compatible with C, so it inherited C's enumerations. 251 However, the following non-backwards compatible changes are made. 228 252 229 253 \begin{cquote} … … 423 447 \begin{Go} 424 448 const ( Mon = iota; Tue; Wed; // 0, 1, 2 425 449 @Thu = 10@; Fri; Sat; Sun ) // 10, 10, 10, 10 426 450 \end{Go} 427 451 Auto-incrementing can be restarted with an expression containing \emph{one} \lstinline[language=Go]{iota}. … … 429 453 const ( V1 = iota; V2; @V3 = 7;@ V4 = @iota@; V5 ) // 0 1 7 3 4 430 454 const ( Mon = iota; Tue; Wed; // 0, 1, 2 431 455 @Thu = 10;@ Fri = @iota - Wed + Thu - 1@; Sat; Sun ) // 10, 11, 12, 13 432 456 \end{Go} 433 457 Note, \lstinline[language=Go]{iota} is advanced for an explicitly initialized enumerator, like the underscore @_@ identifier. … … 1200 1224 \lstnewenvironment{python}[1][]{\lstset{language=Python,escapechar=\$,moredelim=**[is][\color{red}]{@}{@},}\lstset{#1}}{} 1201 1225 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. 1226 A Python enumeration is a set of symbolic names bound to \emph{unique} values. 1227 They are similar to global variables, but offer a more useful @repr()@, grouping, type-safety, and additional features. 1228 Enumerations inherits from the @Enum@ class, \eg: 1229 \begin{python} 1230 class Weekday(@Enum@): Mon = 1; Tue = 2; Wed = 3; Thu = 4; Fri = 5; Sat = 6; Sun = 7 1231 class RGB(@Enum@): Red = 1; Green = 2; Blue = 3 1232 \end{python} 1230 1233 1231 1234 Depending 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: 1232 1235 \begin{python} 1233 >>> Weekday(3)1234 <Weekday.W EDNESDAY: 3>1236 print( repr( Weekday( 3 ) ) ) 1237 <Weekday.Wed: 3> 1235 1238 \end{python} 1236 1239 As you can see, the @repr()@ of a member shows the enum name, the member name, and the value. 1237 1240 The @str()@ of a member shows only the enum name and member name: 1238 1241 \begin{python} 1239 print( Weekday.THURSDAY)1240 Weekday.T HURSDAY1242 print( str( Weekday.Thu ), Weekday.Thu ) 1243 Weekday.Thu Weekday.Thu 1241 1244 \end{python} 1242 1245 The type of an enumeration member is the enum it belongs to: 1243 1246 \begin{python} 1244 >>> type(Weekday.MONDAY)1247 print( type( Weekday.Thu ) ) 1245 1248 <enum 'Weekday'> 1246 isinstance(Weekday.FRIDAY, Weekday)1249 print( isinstance(Weekday.Fri, Weekday) ) 1247 1250 True 1248 1251 \end{python} 1249 1252 Enum members have an attribute that contains just their name: 1250 1253 \begin{python} 1251 >>>print(Weekday.TUESDAY.name)1254 print(Weekday.TUESDAY.name) 1252 1255 TUESDAY 1253 1256 \end{python} 1254 1257 Likewise, they have an attribute for their value: 1255 1258 \begin{python} 1256 >>>Weekday.WEDNESDAY.value1259 Weekday.WEDNESDAY.value 1257 1260 3 1258 1261 \end{python} 1262 1259 1263 Unlike many languages that treat enumerations solely as name/value pairs, Python @Enum@s can have behavior added. 1260 1264 For example, @datetime.date@ has two methods for returning the weekday: @weekday()@ and @isoweekday()@. … … 1262 1266 Rather 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: 1263 1267 \begin{python} 1268 class Weekday(Enum): Mon = 1; Tue = 2; Wed = 3; Thu = 10; Fri = 15; Sat = 16; Sun = 17 1264 1269 $@$classmethod 1265 1270 def 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()) 1271 return cls(date.isoweekday()) 1282 1272 \end{python} 1283 1273 Now we can find out what today is! Observe: … … 1291 1281 This 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@: 1292 1282 \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 1283 from enum import Flag 1284 class WeekdayF(@Flag@): Mon = @1@; Tue = @2@; Wed = @4@; Thu = @8@; Fri = @16@; Sat = @32@; Sun = @64@ 1302 1285 \end{python} 1303 1286 We've changed two things: we're inherited from @Flag@, and the values are all powers of 2. 1304 1287 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> 1288 @Flag@ allows combining several members into a single variable: 1289 \begin{python} 1290 print( repr(WeekdayF.Sat | WeekdayF.Sun) ) 1291 <WeekdayF.Sun|Sat: 96> 1316 1292 \end{python} 1317 1293 You can even iterate over a @Flag@ variable: 1318 1294 \begin{python} 1319 >>>for day in weekend:1320 ...print(day)1295 for day in weekend: 1296 print(day) 1321 1297 Weekday.SATURDAY 1322 1298 Weekday.SUNDAY … … 1382 1358 \subsection{Duplicating enum members and values} 1383 1359 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. 1360 An enum member can have other names associated with it. 1395 1361 Given two entries @A@ and @B@ with the same value (and @A@ defined first), @B@ is an alias for the member @A@. 1396 1362 By-value lookup of the value of @A@ will return the member @A@. … … 1398 1364 By-name lookup of @B@ will also return the member @A@: 1399 1365 \begin{python} 1400 >>> class Shape(Enum): 1401 ... SQUARE = 2 1402 ... DIAMOND = 1 1403 ... CIRCLE = 3 1404 ... ALIAS_FOR_SQUARE = 2 1405 ... 1366 class Shape(Enum): SQUARE = 2; DIAMOND = 1; CIRCLE = 3; ALIAS_FOR_SQUARE = 2 1406 1367 >>> Shape.SQUARE 1407 1368 <Shape.SQUARE: 2> … … 1419 1380 When this behavior isn't desired, you can use the @unique()@ decorator: 1420 1381 \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 ... 1382 from enum import Enum, unique 1383 $@$unique 1384 class DupVal(Enum): ONE = 1; TWO = 2; THREE = 3; FOUR = 3 1431 1385 ValueError: duplicate values found in <enum 'Mistake'>: FOUR -> THREE 1432 1386 \end{python} … … 1436 1390 If the exact value is unimportant you can use @auto@: 1437 1391 \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: 1392 from enum import Enum, auto 1393 class RGBa(Enum): RED = auto(); BLUE = auto(); GREEN = auto() 1394 \end{python} 1395 (Like Golang @iota@.) 1396 The values are chosen by @_generate_next_value_()@, which can be overridden: 1448 1397 \begin{python} 1449 1398 >>> class AutoName(Enum): … … 1582 1531 \begin{python} 1583 1532 class EnumName([mix-in, ...,] [data-type,] base-enum): 1584 1533 pass 1585 1534 \end{python} 1586 1535 Also, subclassing an enumeration is allowed only if the enumeration does not define any members. … … 1699 1648 \begin{python} 1700 1649 Enum( 1701 1702 1703 1704 1705 1706 1707 1708 1650 value='NewEnumName', 1651 names=<...>, 1652 *, 1653 module='...', 1654 qualname='...', 1655 type=<mixed-in class>, 1656 start=1, 1657 ) 1709 1658 \end{python} 1710 1659 \begin{itemize} … … 1935 1884 \begin{python} 1936 1885 class IntEnum(int, Enum): 1937 1886 pass 1938 1887 \end{python} 1939 1888 This demonstrates how similar derived enumerations can be defined; … … 2070 2019 \begin{python} 2071 2020 def __bool__(self): 2072 2021 return bool(self.value) 2073 2022 \end{python} 2074 2023 Plain @Enum@ classes always evaluate as @True@. … … 2414 2363 2415 2364 If @__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} 2365 \begin{figure} 2366 \begin{python} 2367 from enum import Enum 2368 class Planet(Enum): 2369 MERCURY = ( 3.303E23, 2.4397E6 ) 2370 VENUS = ( 4.869E24, 6.0518E6 ) 2371 EARTH = (5.976E24, 6.37814E6) 2372 MARS = (6.421E23, 3.3972E6) 2373 JUPITER = (1.9E27, 7.1492E7) 2374 SATURN = (5.688E26, 6.0268E7) 2375 URANUS = (8.686E25, 2.5559E7) 2376 NEPTUNE = (1.024E26, 2.4746E7) 2377 def __init__( self, mass, radius ): 2378 self.mass = mass # in kilograms 2379 self.radius = radius # in meters 2380 def surface_gravity( self ): 2381 # universal gravitational constant (m3 kg-1 s-2) 2382 G = 6.67300E-11 2383 return G * self.mass / (self.radius * self.radius) 2384 for p in Planet: 2385 print( f"{p.name}: {p.value}" ) 2386 2387 MERCURY: (3.303e+23, 2439700.0) 2388 VENUS: (4.869e+24, 6051800.0) 2389 EARTH: (5.976e+24, 6378140.0) 2390 MARS: (6.421e+23, 3397200.0) 2391 JUPITER: (1.9e+27, 71492000.0) 2392 SATURN: (5.688e+26, 60268000.0) 2393 URANUS: (8.686e+25, 25559000.0) 2394 NEPTUNE: (1.024e+26, 24746000.0) 2395 \end{python} 2396 \caption{Python Planet Example} 2397 \label{f:PythonPlanetExample} 2398 \end{figure} 2399 2440 2400 2441 2401 \subsection{TimePeriod} … … 2464 2424 \section{OCaml} 2465 2425 \lstnewenvironment{ocaml}[1][]{\lstset{language=OCaml,escapechar=\$,moredelim=**[is][\color{red}]{@}{@},}\lstset{#1}}{} 2426 2427 % https://ocaml.org/docs/basic-data-types#enumerated-data-types 2466 2428 2467 2429 OCaml provides a variant (union) type, where multiple heterogeneously-typed objects share the same storage. … … 2553 2515 With valediction, 2554 2516 - Gregor Richards 2517 2518 2519 Date: Thu, 14 Mar 2024 21:45:52 -0400 2520 Subject: Re: OCaml "enums" do come with ordering 2521 To: "Peter A. Buhr" <pabuhr@uwaterloo.ca> 2522 From: Gregor Richards <gregor.richards@uwaterloo.ca> 2523 2524 On 3/14/24 21:30, Peter A. Buhr wrote: 2525 > I've marked 3 places with your name to shows places with enum ordering. 2526 > 2527 > type weekday = Mon | Tue | Wed | Thu | Fri | Sat | Sun 2528 > let day : weekday = Mon 2529 > let take_class( d : weekday ) = 2530 > if d <= Fri then (* Gregor *) 2531 > Printf.printf "weekday\n" 2532 > else if d >= Sat then (* Gregor *) 2533 > Printf.printf "weekend\n"; 2534 > match d with 2535 > Mon | Wed -> Printf.printf "CS442\n" | 2536 > Tue | Thu -> Printf.printf "CS343\n" | 2537 > Fri -> Printf.printf "Tutorial\n" | 2538 > _ -> Printf.printf "Take a break\n" 2539 > 2540 > let _ = take_class( Mon ); take_class( Sat ); 2541 > 2542 > type colour = Red | Green of string | Blue of int * float 2543 > let c = Red 2544 > let _ = match c with Red -> Printf.printf "Red, " 2545 > let c = Green( "abc" ) 2546 > let _ = match c with Green g -> Printf.printf "%s, " g 2547 > let c = Blue( 1, 1.5 ) 2548 > let _ = match c with Blue( i, f ) -> Printf.printf "%d %g\n" i f 2549 > 2550 > let check_colour(c: colour): string = 2551 > if c < Green( "xyz" ) then (* Gregor *) 2552 > Printf.printf "green\n"; 2553 > match c with 2554 > Red -> "Red" | 2555 > Green g -> g | 2556 > Blue(i, f) -> string_of_int i ^ string_of_float f 2557 > let _ = check_colour( Red ); check_colour( Green( "xyz" ) ); 2558 > 2559 > type stringList = Empty | Pair of string * stringList 2560 > let rec len_of_string_list(l: stringList): int = 2561 > match l with 2562 > Empty -> 0 | 2563 > Pair(_ , r) -> 1 + len_of_string_list r 2564 > 2565 > let _ = for i = 1 to 10 do 2566 > Printf.printf "%d, " i 2567 > done 2568 > 2569 > (* Local Variables: *) 2570 > (* tab-width: 4 *) 2571 > (* compile-command: "ocaml test.ml" *) 2572 > (* End: *) 2573 2574 My functional-language familiarity is far more with Haskell than OCaml. I 2575 mostly view OCaml through a lens of "it's Haskell but with cheating". Haskell 2576 "enums" (ADTs) aren't ordered unless you specifically and manually put them in 2577 the Ord typeclass by defining the comparators. Apparently, OCaml has some 2578 other rule, which I would guess is something like "sort by tag then by order of 2579 parameter". Having a default behavior for comparators is *bizarre*; my guess 2580 would be that it gained this behavior in its flirtation with object 2581 orientation, but that's just a guess (and irrelevant). 2582 2583 This gives a total order, but not enumerability (which would still be 2584 effectively impossible or even meaningless since enums are just a special case 2585 of ADTs). 2586 2587 With valediction, 2588 - Gregor Richards 2555 2589 \end{comment} 2556 2590 … … 2558 2592 \section{Comparison} 2559 2593 2560 \begin{tabular}{r|ccccccccc} 2561 feat. / lang. & Pascal & Ada & \Csharp & OCaml & Java & Modula-3 & Rust & Swift & Python \\ 2594 \VRef[Table]{t:FeatureLanguageComparison} shows a comparison of enumeration features and programming languages. 2595 The features are high level and may not capture nuances within a particular language 2596 The @const@ feature is simple macros substitution and not a typed enumeration. 2597 2598 \begin{table} 2599 \caption{Enumeration Feature / Language Comparison} 2600 \label{t:FeatureLanguageComparison} 2601 \small 2602 \setlength{\tabcolsep}{3pt} 2603 \newcommand{\CM}{\checkmark} 2604 \begin{tabular}{r|c|c|c|c|c|c|c|c|c|c|c|c|c} 2605 &Pascal & Ada &\Csharp& OCaml & Java &Modula-3&Golang& Rust & Swift & Python& C & \CC & \CFA \\ 2562 2606 \hline 2563 pure & & & & & & & & & \\ 2564 ordered & & & & & & & & & \\ 2565 setable & & & & & & & & & \\ 2566 auto-init & & & & & & & & & \\ 2567 scoped & & & & & & & & & \\ 2568 typed & & & & & & & & & \\ 2569 switch & & & & & & & & & \\ 2570 loop & & & & & & & & & \\ 2571 array & & & & & & & & & \\ 2607 @const@ & \CM & & & & & & \CM & & & & & \CM & \\ 2608 \hline 2609 \hline 2610 pure & & & & & & & & & & & & & \CM \\ 2611 \hline 2612 typed & & & & & & & & & & & @int@ & integral & @T@ \\ 2613 \hline 2614 safe & & & & & & & & & & & & \CM & \CM \\ 2615 \hline 2616 ordered & & & & & & & & & & & \CM & \CM & \CM \\ 2617 \hline 2618 dup. values & & & & & & & & & & alias & \CM & \CM & \CM \\ 2619 \hline 2620 setable & & & & & & & & & & & \CM & \CM & \CM \\ 2621 \hline 2622 auto-init & & & & & & & & & & & \CM & \CM & \CM \\ 2623 \hline 2624 (un)scoped & & & & & & & & & & & U & U/S & U/S \\ 2625 \hline 2626 overload & & \CM & & & & & & & & & & \CM & \CM \\ 2627 \hline 2628 switch & & & & & & & & & & & \CM & \CM & \CM \\ 2629 \hline 2630 loop & & & & & & & & & & & & & \CM \\ 2631 \hline 2632 array & & & & & & & & & & & \CM & & \CM \\ 2633 \hline 2634 subtype & & & & & & & & & & & & & \CM \\ 2635 \hline 2636 inheritance & & & & & & & & & & & & & \CM \\ 2572 2637 \end{tabular} 2638 \end{table}
Note: See TracChangeset
for help on using the changeset viewer.