Changeset f936e23 for doc/theses/jiada_liang_MMath/relatedwork.tex
- Timestamp:
- Feb 13, 2024, 4:10:20 PM (4 months ago)
- Branches:
- master
- Children:
- c2a58cf
- Parents:
- acde87a
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/theses/jiada_liang_MMath/relatedwork.tex
racde87a rf936e23 5 5 There are a large set of overlapping features among these languages, but each language has its own unique restrictions and extensions. 6 6 7 7 8 \section{(Free) Pascal} 9 10 \lstnewenvironment{pascal}[1][]{% necessary 11 \lstset{ 12 language=pascal, 13 escapechar=\$, % LaTeX escape in CFA code 14 moredelim=**[is][\color{red}]{@}{@}, % red highlighting @...@ 15 }% lstset 16 \lstset{#1}% necessary 17 }{} 8 18 9 19 Free Pascal is a modern object-oriented version of the classic Pascal programming language. 10 20 It allows a C-style enumeration type, where enumerators must be in assigned in ascending numerical order with a constant expression and the range can be non-consecutive. 11 \begin{ lstlisting}[language=pascal,{moredelim=**[is][\color{red}]{@}{@}}]21 \begin{pascal} 12 22 Type EnumType = ( one, two, three, forty @= 40@, fortyone ); 13 \end{ lstlisting}23 \end{pascal} 14 24 Pseudo-functions @Pred@ and @Succ@ can only be used if the range is consecutive. 15 25 The underlying type is an implementation-defined integral type large enough to hold all enumerated values; it does not have to be the smallest possible type. 16 26 The size underlying integral type can be explicitly specified using compiler directive @$PACKENUM@~$N$, where $N$ is the number of bytes, e.g.: 17 \begin{ lstlisting}[language=pascal,{moredelim=**[is][\color{red}]{@}{@}}]27 \begin{pascal} 18 28 Type @{$\color{red}\$$PACKENUM 1}@ SmallEnum = ( one, two, three ); 19 29 @{$\color{red}\$$PACKENUM 4}@ LargeEnum = ( BigOne, BigTwo, BigThree ); 20 30 Var S : SmallEnum; { 1 byte } 21 31 L : LargeEnum; { 4 bytes} 22 \end{ lstlisting}32 \end{pascal} 23 33 24 34 25 35 \section{Ada} 26 36 37 \lstnewenvironment{ada}[1][]{% necessary 38 \lstset{ 39 language=ada, 40 escapechar=\$, % LaTeX escape in CFA code 41 moredelim=**[is][\color{red}]{@}{@}, % red highlighting @...@ 42 }% lstset 43 \lstset{#1}% necessary 44 }{} 45 27 46 An enumeration type is defined as a list of possible values: 28 \begin{ lstlisting}[language=ada]47 \begin{ada} 29 48 type RGB is (Red, Green, Blue); 30 \end{ lstlisting}49 \end{ada} 31 50 Like for numeric types, where e.g., 1 is an integer literal, @Red@, @Green@ and @Blue@ are called the literals of this type. 32 51 There are no other values assignable to objects of this type. … … 36 55 Each literal has a position, starting with 0 for the first, incremented by one for each successor. 37 56 This position can be queried via the @'Pos@ attribute; the inverse is @'Val@, which returns the corresponding literal. In our example: 38 \begin{ lstlisting}[language=ada]57 \begin{ada} 39 58 RGB'Pos (Red) = 0 40 59 RGB'Val (0) = Red 41 \end{ lstlisting}60 \end{ada} 42 61 There are two other important attributes: @Image@ and @Value@. 43 62 @Image@ returns the string representation of the value (in capital letters), @Value@ is the inverse: 44 \begin{ lstlisting}[language=ada]63 \begin{ada} 45 64 RGB'Image ( Red ) = "RED" 46 65 RGB'Value ("Red") = Red 47 \end{ lstlisting}66 \end{ada} 48 67 These attributes are important for simple IO (there are more elaborate IO facilities in @Ada.Text_IO@ for enumeration types). 49 68 Note that, since Ada is case-insensitive, the string given to @'Value@ can be in any case. … … 51 70 \paragraph{Enumeration literals} ~\newline 52 71 Literals are overloadable, i.e. you can have another type with the same literals. 53 \begin{ lstlisting}[language=ada]72 \begin{ada} 54 73 type Traffic_Light is (Red, Yellow, Green); 55 \end{ lstlisting}74 \end{ada} 56 75 Overload resolution within the context of use of a literal normally resolves which @Red@ is meant. 57 76 Only if you have an unresolvable overloading conflict, you can qualify with special syntax which @Red@ is meant: 58 \begin{ lstlisting}[language=ada]77 \begin{ada} 59 78 RGB'(Red) 60 \end{ lstlisting}79 \end{ada} 61 80 Like many other declarative items, enumeration literals can be renamed. 62 81 In fact, such a literal is actually a function, so it has to be renamed as such: 63 \begin{ lstlisting}[language=ada]82 \begin{ada} 64 83 function Red return P.RGB renames P.Red; 65 \end{ lstlisting}84 \end{ada} 66 85 Here, @RGB@ is assumed to be defined in package @P@, which is visible at the place of the renaming declaration. 67 86 Renaming makes @Red@ directly visible without necessity to resort the use-clause. … … 71 90 \paragraph{Characters as enumeration literals} ~\newline 72 91 Rather unique to Ada is the use of character literals as enumeration literals: 73 \begin{ lstlisting}[language=ada]92 \begin{ada} 74 93 type ABC is ('A', 'B', 'C'); 75 \end{ lstlisting}94 \end{ada} 76 95 This literal @'A'@ has nothing in common with the literal @'A'@ of the predefined type @Character@ (or @Wide_Character@). 77 96 78 97 Every type that has at least one character literal is a character type. 79 98 For every character type, string literals and the concatenation operator @"&"@ are also implicitly defined. 80 \begin{ lstlisting}[language=ada]99 \begin{ada} 81 100 type My_Character is (No_Character, 'a', Literal, 'z'); 82 101 type My_String is array (Positive range <>) of My_Character; … … 84 103 S: My_String := "aa" & Literal & "za" & 'z'; 85 104 T: My_String := ('a', 'a', Literal, 'z', 'a', 'z'); 86 \end{ lstlisting}105 \end{ada} 87 106 In this example, @S@ and @T@ have the same value. 88 107 … … 92 111 \paragraph{Booleans as enumeration literals} ~\newline 93 112 Also Booleans are defined as enumeration types: 94 \begin{ lstlisting}[language=ada]113 \begin{ada} 95 114 type Boolean is (False, True); 96 \end{ lstlisting}115 \end{ada} 97 116 There is special semantics implied with this declaration in that objects and expressions of this type can be used as conditions. 98 117 Note that the literals @False@ and @True@ are not Ada keywords. 99 118 100 119 Thus it is not sufficient to declare a type with these literals and then hope objects of this type can be used like so: 101 \begin{ lstlisting}[language=ada]120 \begin{ada} 102 121 type My_Boolean is (False, True); 103 122 Condition: My_Boolean; 104 123 105 124 if Condition then -- wrong, won't compile 106 \end{ lstlisting}125 \end{ada} 107 126 108 127 If you need your own Booleans (perhaps with special size requirements), you have to derive from the predefined Boolean: 109 \begin{ lstlisting}[language=ada]128 \begin{ada} 110 129 type My_Boolean is new Boolean; 111 130 Condition: My_Boolean; 112 131 113 132 if Condition then -- OK 114 \end{ lstlisting}133 \end{ada} 115 134 116 135 \paragraph{Enumeration subtypes} ~\newline 117 136 You can use range to subtype an enumeration type: 118 \begin{ lstlisting}[language=ada]137 \begin{ada} 119 138 subtype Capital_Letter is Character range 'A' .. 'Z'; 120 139 type Day_Of_Week is (Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday); 121 140 subtype Working_Day is Day_Of_Week range Monday .. Friday; 122 \end{ lstlisting}141 \end{ada} 123 142 124 143 \paragraph{Using enumerations} ~\newline 125 144 Enumeration types being scalar subtypes, type attributes such as @First@ and @Succ@ will allow stepping through a subsequence of the values. 126 \begin{ lstlisting}[language=ada]145 \begin{ada} 127 146 case Day_Of_Week'First is 128 147 when Sunday => … … 133 152 raise Program_Error; 134 153 end case; 135 \end{ lstlisting}154 \end{ada} 136 155 A loop will automatically step through the values of the subtype's range. 137 156 Filtering week days to include only working days with an even position number: 138 \begin{ lstlisting}[language=ada]157 \begin{ada} 139 158 for Day in Working_Day loop 140 159 if Day_Of_Week'Pos(Day) mod 2 = 0 then … … 142 161 end if; 143 162 end loop; 144 \end{ lstlisting}163 \end{ada} 145 164 Enumeration types can be used as array index subtypes, yielding a table feature: 146 \begin{ lstlisting}[language=ada]165 \begin{ada} 147 166 type Officer_ID is range 0 .. 50; 148 167 type Schedule is array (Working_Day) of Officer_ID; 149 \end{ lstlisting}150 151 \begin{ lstlisting}[language=ada]168 \end{ada} 169 170 \begin{ada} 152 171 type Subtype_Name is (Id1, Id2, Id3 ... ); 153 \end{ lstlisting}172 \end{ada} 154 173 where @Id1@, @Id2@, etc. are identifiers or characters literals. 155 174 In either case, the legal values of the type are referred to as "enumeration literals." … … 171 190 \section{C\raisebox{-0.7ex}{\LARGE$^\sharp$}\xspace} % latex bug: cannot use \relsize{2} so use \LARGE 172 191 173 \lstdefinelanguage{swift} 192 \lstnewenvironment{csharp}[1][]{% necessary 193 \lstset{ 194 language=[Sharp]C, 195 escapechar=\$, % LaTeX escape in CFA code 196 moredelim=**[is][\color{red}]{@}{@}, % red highlighting @...@ 197 }% lstset 198 \lstset{#1}% necessary 199 }{} 200 201 An enumeration type (or enum type) is a value type defined by a set of named constants of the underlying integral numeric type. 202 To define an enumeration type, use the enum keyword and specify the names of enum members: 203 \begin{csharp} 204 enum Season { 205 Spring, 206 Summer, 207 Autumn, 208 Winter 209 } 210 \end{csharp} 211 By default, the associated constant values of enum members are of type @int@; 212 they start with zero and increase by one following the definition text order. 213 214 You can explicitly specify any other integral numeric type as an underlying type of an enumeration type. 215 You can also explicitly specify the associated constant values, as the following example shows: 216 \begin{csharp} 217 enum ErrorCode : ushort { 218 None = 0, 219 Unknown = 1, 220 ConnectionLost = 100, 221 OutlierReading = 200 222 } 223 \end{csharp} 224 You cannot define a method inside the definition of an enumeration type. 225 To add functionality to an enumeration type, create an extension method. 226 227 The default value of an enumeration type @E@ is the value produced by expression @(E)0@, even if zero doesn't have the corresponding enum member. 228 229 You use an enumeration type to represent a choice from a set of mutually exclusive values or a combination of choices. 230 To represent a combination of choices, define an enumeration type as bit flags. 231 232 \paragraph{Enumeration types as bit flags} 233 234 If you want an enumeration type to represent a combination of choices, define enum members for those choices such that an individual choice is a bit field. 235 That is, the associated values of those enum members should be the powers of two. 236 Then, you can use the bitwise logical operators @|@ or @&@ to combine choices or intersect combinations of choices, respectively. 237 To indicate that an enumeration type declares bit fields, apply the @Flags@ attribute to it. 238 As the following example shows, you can also include some typical combinations in the definition of an enumeration type. 239 \begin{csharp} 240 [Flags] 241 public enum Days { 242 None = 0b_0000_0000, // 0 243 Monday = 0b_0000_0001, // 1 244 Tuesday = 0b_0000_0010, // 2 245 Wednesday = 0b_0000_0100, // 4 246 Thursday = 0b_0000_1000, // 8 247 Friday = 0b_0001_0000, // 16 248 Saturday = 0b_0010_0000, // 32 249 Sunday = 0b_0100_0000, // 64 250 Weekend = Saturday | Sunday 251 } 252 253 public class FlagsEnumExample { 254 public static void Main() { 255 Days meetingDays = Days.Monday | Days.Wednesday | Days.Friday; 256 Console.WriteLine(meetingDays); 257 // Output: 258 // Monday, Wednesday, Friday 259 260 Days workingFromHomeDays = Days.Thursday | Days.Friday; 261 Console.WriteLine($\$$"Join a meeting by phone on {meetingDays & workingFromHomeDays}"); 262 // Output: 263 // Join a meeting by phone on Friday 264 265 bool isMeetingOnTuesday = (meetingDays & Days.Tuesday) == Days.Tuesday; 266 Console.WriteLine($\$$"Is there a meeting on Tuesday: {isMeetingOnTuesday}"); 267 // Output: 268 // Is there a meeting on Tuesday: False 269 270 var a = (Days)37; 271 Console.WriteLine(a); 272 // Output: 273 // Monday, Wednesday, Saturday 274 } 275 } 276 \end{csharp} 277 For more information and examples, see the System.FlagsAttribute API reference page and the Non-exclusive members and the Flags attribute section of the System.Enum API reference page. 278 279 \paragraph{The System.Enum type and enum constraint} 280 281 The System.Enum type is the abstract base class of all enumeration types. 282 It provides a number of methods to get information about an enumeration type and its values. 283 For more information and examples, see the System.Enum API reference page. 284 285 You can use System.Enum in a base class constraint (that is known as the enum constraint) to specify that a type parameter is an enumeration type. 286 Any enumeration type also satisfies the struct constraint, which is used to specify that a type parameter is a non-nullable value type. 287 Conversions 288 289 For any enumeration type, there exist explicit conversions between the enumeration type and its underlying integral type. 290 If you cast an enum value to its underlying type, the result is the associated integral value of an enum member. 291 \begin{csharp} 292 public enum Season 174 293 { 175 morekeywords={ 176 open,catch,@escaping,nil,throws,func,if,then,else,for,in,while,do,switch,case,default,where,break,continue,fallthrough,return, 177 typealias,struct,class,enum,protocol,var,func,let,get,set,willSet,didSet,inout,init,deinit,extension, 178 subscript,prefix,operator,infix,postfix,precedence,associativity,left,right,none,convenience,dynamic, 179 final,lazy,mutating,nonmutating,optional,override,required,static,unowned,safe,weak,internal, 180 private,public,is,as,self,unsafe,dynamicType,true,false,nil,Type,Protocol, 181 }, 182 morecomment=[l]{//}, % l is for line comment 183 morecomment=[s]{/*}{*/}, % s is for start and end delimiter 184 morestring=[b]", % defines that strings are enclosed in double quotes 185 breaklines=true, 186 escapeinside={\%*}{*)}, 187 % numbers=left, 188 captionpos=b, 189 breakatwhitespace=true, 190 basicstyle=\linespread{0.9}\sf, % https://tex.stackexchange.com/a/102728/129441 191 } 192 193 Model custom types that define a list of possible values. 194 195 An 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. 196 197 If you are familiar with C, you will know that C enumerations assign related names to a set of integer values. 198 Enumerations in Swift are much more flexible, and don't have to provide a value for each case of the enumeration. 199 If 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. 200 201 Alternatively, 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. 202 You 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. 203 204 Enumerations in Swift are first-class types in their own right. 205 They 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. 206 Enumerations can also define initializers to provide an initial case value; 207 can be extended to expand their functionality beyond their original implementation; and can conform to protocols to provide standard functionality. 208 209 For more about these capabilities, see Properties, Methods, Initialization, Extensions, and Protocols. 210 211 \paragraph{Enumeration Syntax} 212 213 You introduce enumerations with the @enum@ keyword and place their entire definition within a pair of braces: 214 \begin{lstlisting}[language=swift] 215 enum SomeEnumeration { 216 // enumeration definition goes here 217 } 218 \end{lstlisting} 219 Here's an example for the four main points of a compass: 220 \begin{lstlisting}[language=swift] 221 enum CompassPoint { 222 case north 223 case south 224 case east 225 case west 226 } 227 \end{lstlisting} 228 The values defined in an enumeration (such as @north@, @south@, @east@, and @west@) are its enumeration cases. 229 You use the @case@ keyword to introduce new enumeration cases. 230 231 Note: 232 Swift enumeration cases don't have an integer value set by default, unlike languages like C and Objective-C. 233 In the CompassPoint example above, @north@, @south@, @east@ and @west@ don't implicitly equal 0, 1, 2 and 3. 234 Instead, the different enumeration cases are values in their own right, with an explicitly defined type of CompassPoint. 235 236 Multiple cases can appear on a single line, separated by commas: 237 \begin{lstlisting}[language=swift] 238 enum Planet { 239 case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune 240 } 241 \end{lstlisting} 242 Each enumeration definition defines a new type. 243 Like other types in Swift, their names (such as @CompassPoint@ and @Planet@) start with a capital letter. 244 Give enumeration types singular rather than plural names, so that they read as self-evident: 245 \begin{lstlisting}[language=swift] 246 var directionToHead = CompassPoint.west 247 \end{lstlisting} 248 The type of @directionToHead@ is inferred when it's initialized with one of the possible values of @CompassPoint@. 249 Once @directionToHead@ is declared as a @CompassPoint@, you can set it to a different @CompassPoint@ value using a shorter dot syntax: 250 \begin{lstlisting}[language=swift] 251 directionToHead = .east 252 \end{lstlisting} 253 The type of @directionToHead@ is already known, and so you can drop the type when setting its value. 254 This makes for highly readable code when working with explicitly typed enumeration values. 255 256 \paragraph{Matching Enumeration Values with a Switch Statement} 257 258 You can match individual enumeration values with a switch statement: 259 \begin{lstlisting}[language=swift] 260 directionToHead = .south 261 switch directionToHead { 262 case .north: 263 print("Lots of planets have a north") 264 case .south: 265 print("Watch out for penguins") 266 case .east: 267 print("Where the sun rises") 268 case .west: 269 print("Where the skies are blue") 270 } 271 // Prints "Watch out for penguins" 272 \end{lstlisting} 273 You can read this code as: 274 \begin{quote} 275 "Consider the value of directionToHead. 276 In the case where it equals @.north@, print "Lots of planets have a north". 277 In the case where it equals @.south@, print "Watch out for penguins"." 278 279 ...and so on. 280 \end{quote} 281 As described in Control Flow, a switch statement must be exhaustive when considering an enumeration's cases. 282 If the case for @.west@ is omitted, this code doesn't compile, because it doesn't consider the complete list of @CompassPoint@ cases. 283 Requiring exhaustiveness ensures that enumeration cases aren't accidentally omitted. 284 285 When 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: 286 \begin{lstlisting}[language=swift] 287 let somePlanet = Planet.earth 288 switch somePlanet { 289 case .earth: 290 print("Mostly harmless") 291 default: 292 print("Not a safe place for humans") 293 } 294 // Prints "Mostly harmless" 295 \end{lstlisting} 296 297 \paragraph{Iterating over Enumeration Cases} 298 299 For some enumerations, it's useful to have a collection of all of that enumeration's cases. 300 You enable this by writing @CaseIterable@ after the enumeration's name. 301 Swift exposes a collection of all the cases as an allCases property of the enumeration type. 302 Here's an example: 303 \begin{lstlisting}[language=swift] 304 enum Beverage: CaseIterable { 305 case coffee, tea, juice 306 } 307 let numberOfChoices = Beverage.allCases.count 308 print("\(numberOfChoices) beverages available") 309 // Prints "3 beverages available" 310 \end{lstlisting} 311 In the example above, you write @Beverage.allCases@ to access a collection that contains all of the cases of the @Beverage@ enumeration. 312 You 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. 313 The example above counts how many cases there are, and the example below uses a for-in loop to iterate over all the cases. 314 \begin{lstlisting}[language=swift] 315 for beverage in Beverage.allCases { 316 print(beverage) 317 } 318 // coffee 319 // tea 320 // juice 321 \end{lstlisting} 322 The syntax used in the examples above marks the enumeration as conforming to the @CaseIterable@ protocol. 323 For information about protocols, see Protocols. 324 325 \paragraph{Associated Values} 326 The examples in the previous section show how the cases of an enumeration are a defined (and typed) value in their own right. 327 You can set a constant or variable to Planet.earth, and check for this value later. 328 However, it's sometimes useful to be able to store values of other types alongside these case values. 329 This additional information is called an associated value, and it varies each time you use that case as a value in your code. 330 331 You 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. 332 Enumerations similar to these are known as discriminated unions, tagged unions, or variants in other programming languages. 333 334 For example, suppose an inventory tracking system needs to track products by two different types of barcode. 335 Some products are labeled with 1D barcodes in UPC format, which uses the numbers 0 to 9. 336 Each barcode has a number system digit, followed by five manufacturer code digits and five product code digits. 337 These are followed by a check digit to verify that the code has been scanned correctly: 338 339 Other 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: 340 341 It'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. 342 343 In Swift, an enumeration to define product barcodes of either type might look like this: 344 \begin{lstlisting}[language=swift] 345 enum Barcode { 346 case upc(Int, Int, Int, Int) 347 case qrCode(String) 348 } 349 \end{lstlisting} 350 This can be read as: 351 \begin{quote} 352 "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@." 353 \end{quote} 354 This 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@. 355 356 You can then create new barcodes using either type: 357 \begin{lstlisting}[language=swift] 358 var productBarcode = Barcode.upc(8, 85909, 51226, 3) 359 \end{lstlisting} 360 This 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)@. 361 362 You can assign the same product a different type of barcode: 363 \begin{lstlisting}[language=swift] 364 productBarcode = .qrCode("ABCDEFGHIJKLMNOP") 365 \end{lstlisting} 366 At this point, the original @Barcode.upc@ and its integer values are replaced by the new @Barcode.qrCode@ and its string value. 367 Constants 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. 368 369 You can check the different barcode types using a switch statement, similar to the example in Matching Enumeration Values with a Switch Statement. 370 This time, however, the associated values are extracted as part of the switch statement. 371 You 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: 372 \begin{lstlisting}[language=swift][language=swift] 373 switch productBarcode { 374 case .upc(let numberSystem, let manufacturer, let product, let check): 375 print("UPC: \(numberSystem), \(manufacturer), \(product), \(check).") 376 case .qrCode(let productCode): 377 print("QR code: \(productCode).") 378 } 379 // Prints "QR code: ABCDEFGHIJKLMNOP." 380 \end{lstlisting} 381 If 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: 382 \begin{lstlisting}[language=swift] 383 switch productBarcode { 384 case let .upc(numberSystem, manufacturer, product, check): 385 print("UPC : \(numberSystem), \(manufacturer), \(product), \(check).") 386 case let .qrCode(productCode): 387 print("QR code: \(productCode).") 388 } 389 // Prints "QR code: ABCDEFGHIJKLMNOP." 390 \end{lstlisting} 391 392 \paragraph{Raw Values} 393 394 The barcode example in Associated Values shows how cases of an enumeration can declare that they store associated values of different types. 395 As an alternative to associated values, enumeration cases can come prepopulated with default values (called raw values), which are all of the same type. 396 397 Here's an example that stores raw ASCII values alongside named enumeration cases: 398 \begin{lstlisting}[language=swift] 399 enum ASCIIControlCharacter: Character { 400 case tab = "\t" 401 case lineFeed = "\n" 402 case carriageReturn = "\r" 403 } 404 \end{lstlisting} 405 Here, 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. 406 Character values are described in Strings and Characters. 407 408 Raw values can be strings, characters, or any of the integer or floating-point number types. 409 Each raw value must be unique within its enumeration declaration. 410 411 Note 412 413 Raw values are not the same as associated values. 414 Raw values are set to prepopulated values when you first define the enumeration in your code, like the three ASCII codes above. 415 The raw value for a particular enumeration case is always the same. 416 Associated 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. 417 Implicitly Assigned Raw Values 418 419 When 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. 420 When you don't, Swift automatically assigns the values for you. 421 422 For example, when integers are used for raw values, the implicit value for each case is one more than the previous case. 423 If the first case doesn't have a value set, its value is 0. 424 425 The enumeration below is a refinement of the earlier Planet enumeration, with integer raw values to represent each planet's order from the sun: 426 427 \begin{lstlisting}[language=swift] 428 enum Planet: Int { 429 case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune 430 } 431 \end{lstlisting} 432 In the example above, Planet.mercury has an explicit raw value of 1, Planet.venus has an implicit raw value of 2, and so on. 433 434 When strings are used for raw values, the implicit value for each case is the text of that case's name. 435 436 The enumeration below is a refinement of the earlier CompassPoint enumeration, with string raw values to represent each direction's name: 437 \begin{lstlisting}[language=swift] 438 enum CompassPoint: String { 439 case north, south, east, west 440 } 441 \end{lstlisting} 442 In the example above, CompassPoint.south has an implicit raw value of "south", and so on. 443 444 You access the raw value of an enumeration case with its rawValue property: 445 \begin{lstlisting}[language=swift] 446 let earthsOrder = Planet.earth.rawValue 447 // earthsOrder is 3 448 449 let sunsetDirection = CompassPoint.west.rawValue 450 // sunsetDirection is "west" 451 \end{lstlisting} 452 453 \paragraph{Initializing from a Raw Value} 454 455 If 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. 456 You can use this initializer to try to create a new instance of the enumeration. 457 458 This example identifies Uranus from its raw value of 7: 459 \begin{lstlisting}[language=swift] 460 let possiblePlanet = Planet(rawValue: 7) 461 // possiblePlanet is of type Planet? and equals Planet.uranus 462 \end{lstlisting} 463 Not all possible Int values will find a matching planet, however. 464 Because of this, the raw value initializer always returns an optional enumeration case. 465 In the example above, possiblePlanet is of type Planet?, or "optional Planet." 466 Note 467 468 The raw value initializer is a failable initializer, because not every raw value will return an enumeration case. 469 For more information, see Failable Initializers. 470 471 If you try to find a planet with a position of 11, the optional Planet value returned by the raw value initializer will be nil: 472 \begin{lstlisting}[language=swift] 473 let positionToFind = 11 474 if let somePlanet = Planet(rawValue: positionToFind) { 475 switch somePlanet { 476 case .earth: 477 print("Mostly harmless") 478 default: 479 print("Not a safe place for humans") 480 } 481 } else { 482 print("There isn't a planet at position \(positionToFind)") 483 } 484 // Prints "There isn't a planet at position 11" 485 \end{lstlisting} 486 This example uses optional binding to try to access a planet with a raw value of 11. 487 The 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. 488 In this case, it isn't possible to retrieve a planet with a position of 11, and so the else branch is executed instead. 489 490 \paragraph{Recursive Enumerations} 491 492 A recursive enumeration is an enumeration that has another instance of the enumeration as the associated value for one or more of the enumeration cases. 493 You indicate that an enumeration case is recursive by writing indirect before it, which tells the compiler to insert the necessary layer of indirection. 494 495 For example, here is an enumeration that stores simple arithmetic expressions: 496 \begin{lstlisting}[language=swift] 497 enum ArithmeticExpression { 498 case number(Int) 499 indirect case addition(ArithmeticExpression, ArithmeticExpression) 500 indirect case multiplication(ArithmeticExpression, ArithmeticExpression) 501 } 502 \end{lstlisting} 503 You 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: 504 \begin{lstlisting}[language=swift] 505 indirect enum ArithmeticExpression { 506 case number(Int) 507 case addition(ArithmeticExpression, ArithmeticExpression) 508 case multiplication(ArithmeticExpression, ArithmeticExpression) 509 } 510 \end{lstlisting} 511 This enumeration can store three kinds of arithmetic expressions: a plain number, the addition of two expressions, and the multiplication of two expressions. 512 The addition and multiplication cases have associated values that are also arithmetic expressions -- these associated values make it possible to nest expressions. 513 For 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. 514 Because the data is nested, the enumeration used to store the data also needs to support nesting -- this means the enumeration needs to be recursive. 515 The code below shows the ArithmeticExpression recursive enumeration being created for (5 + 4) * 2: 516 \begin{lstlisting}[language=swift] 517 let five = ArithmeticExpression.number(5) 518 let four = ArithmeticExpression.number(4) 519 let sum = ArithmeticExpression.addition(five, four) 520 let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2)) 521 \end{lstlisting} 522 A recursive function is a straightforward way to work with data that has a recursive structure. 523 For example, here's a function that evaluates an arithmetic expression: 524 \begin{lstlisting}[language=swift] 525 func evaluate(_ expression: ArithmeticExpression) -> Int { 526 switch expression { 527 case let .number(value): 528 return value 529 case let .addition(left, right): 530 return evaluate(left) + evaluate(right) 531 case let .multiplication(left, right): 532 return evaluate(left) * evaluate(right) 533 } 534 } 535 536 print(evaluate(product)) 537 // Prints "18" 538 \end{lstlisting} 539 This function evaluates a plain number by simply returning the associated value. 540 It 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. 294 Spring, 295 Summer, 296 Autumn, 297 Winter 298 } 299 300 public class EnumConversionExample 301 { 302 public static void Main() 303 { 304 Season a = Season.Autumn; 305 Console.WriteLine($\$$"Integral value of {a} is {(int)a}"); // output: Integral value of Autumn is 2 306 307 var b = (Season)1; 308 Console.WriteLine(b); // output: Summer 309 310 var c = (Season)4; 311 Console.WriteLine(c); // output: 4 312 } 313 } 314 \end{csharp} 541 315 542 316 543 317 \section{\CC} 544 318 \label{s:C++RelatedWork} 319 320 \lstnewenvironment{c++}[1][]{% necessary 321 \lstset{ 322 language=C++, 323 escapechar=\$, % LaTeX escape in CFA code 324 moredelim=**[is][\color{red}]{@}{@}, % red highlighting @...@ 325 }% lstset 326 \lstset{#1}% necessary 327 }{} 545 328 546 329 \CC is backwards compatible with C, so it inherited C's enumerations. … … 550 333 In C, objects of enumeration type can be assigned values of any integral type. \\ 551 334 Example: 552 \begin{ lstlisting}[language=c++]335 \begin{c++} 553 336 enum color { red, blue, green }; 554 337 color c = 1; $\C{// valid C, invalid C++}$ 555 \end{ lstlisting}556 \textbf{Rationale}: The type-safe nature of C++. \\338 \end{c++} 339 \textbf{Rationale}: The type-safe nature of \CC. \\ 557 340 \textbf{Effect on original feature}: Deletion of semantically well-defined feature. \\ 558 341 \textbf{Difficulty of converting}: Syntactic transformation. (The type error produced by the assignment can be automatically corrected by applying an explicit cast.) \\ … … 563 346 In C, the type of an enumerator is @int@. \\ 564 347 Example: 565 \begin{ lstlisting}[language=c++]348 \begin{c++} 566 349 enum e { A }; 567 350 sizeof(A) == sizeof(int) $\C{// in C}$ 568 351 sizeof(A) == sizeof(e) $\C{// in C++}$ 569 352 /* and sizeof(int) is not necessary equal to sizeof(e) */ 570 \end{ lstlisting}571 \textbf{Rationale}: In C++, an enumeration is a distinct type. \\353 \end{c++} 354 \textbf{Rationale}: In \CC, an enumeration is a distinct type. \\ 572 355 \textbf{Effect on original feature}: Change to semantics of well-defined feature. \\ 573 356 \textbf{Difficulty of converting}: Semantic transformation. \\ … … 577 360 Hence, the values in a \CC enumeration can only be its enumerators (without a cast). 578 361 While the storage size of an enumerator is up to the compiler, there is still an implicit cast to @int@. 579 \begin{ lstlisting}[language=c++]362 \begin{c++} 580 363 enum E { A, B, C }; 581 364 E e = A; 582 365 int i = A; i = e; $\C{// implicit casts to int}$ 583 \end{ lstlisting}366 \end{c++} 584 367 \CC{11} added a scoped enumeration, \lstinline[language=c++]{enum class} (or \lstinline[language=c++]{enum struct}), so the enumerators are local to the enumeration and must be accessed using type qualification. 585 \begin{ lstlisting}[language=c++,{moredelim=**[is][\color{red}]{@}{@}}]368 \begin{c++} 586 369 enum class E { A, B, C }; 587 370 E e = @E::@A; $\C{// qualified enumerator}$ 588 371 e = B; $\C{// B not in scope}$ 589 \end{ lstlisting}372 \end{c++} 590 373 \CC{20} supports unscoped access with a \lstinline[language=c++]{using enum} declaration. 591 \begin{ lstlisting}[language=c++,{moredelim=**[is][\color{red}]{@}{@}}]374 \begin{c++} 592 375 enum class E { A, B, C }; 593 376 @using enum E;@ 594 377 E e = A; $\C{// direct access}$ 595 378 e = B; $\C{// direct access}$ 596 \end{ lstlisting}379 \end{c++} 597 380 \CC{11} added the ability to explicitly declare the underlying integral type for \lstinline[language=c++]{enum class}. 598 \begin{ lstlisting}[language=c++,{moredelim=**[is][\color{red}]{@}{@}}]381 \begin{c++} 599 382 enum class RGB @: long@ { Red, Green, Blue }; 600 383 enum class rgb @: char@ { Red = 'r', Green = 'g', Blue = 'b' }; 601 384 enum class srgb @: signed char@ { Red = -1, Green = 0, Blue = 1 }; 602 \end{ lstlisting}385 \end{c++} 603 386 There is no implicit conversion from the \lstinline[language=c++]{enum class} type and to its type. 604 \begin{ lstlisting}[language=c++,{moredelim=**[is][\color{red}]{@}{@}}]387 \begin{c++} 605 388 rgb crgb = rgb::Red; 606 389 char ch = rgb::Red; ch = crgb; $\C{// disallowed}$ 607 \end{ lstlisting}390 \end{c++} 608 391 Finally, there is no mechanism to iterate through an enumeration nor use the enumeration type to declare an array dimension. 609 392 … … 611 394 \section{Go} 612 395 396 \lstnewenvironment{Go}[1][]{% necessary 397 \lstset{ 398 language=Go, 399 escapechar=\$, % LaTeX escape in CFA code 400 moredelim=**[is][\color{red}]{@}{@}, % red highlighting @...@ 401 }% lstset 402 \lstset{#1}% necessary 403 }{} 404 405 What Is an Enum in Golang? 406 407 An enumerator, or enum, is a data type in Golang that consists of a set of named, constant values. While Golang doesn't support enums, it can be implemented using the identifier iota with constants. 408 409 However, in Golang, they're implemented quite differently than most other programming languages. Golang doesn't support enums directly, however, we can implement it using iota and constants. 410 411 In order to implement enums in Golang, let's first understand what iota is and how it is used. 412 413 414 What Is Iota in Golang? 415 416 iota is an identifier that is used with constant and can simplify constant definitions that use auto-increment numbers. The iota keyword represents integer constant starting from zero. 417 418 The iota keyword represents successive integer constants 0, 1, 2, \ldots. 419 It resets to 0 whenever the word const appears in the source code and increments after each const specification. 420 \begin{Go} 421 package main 422 423 import "fmt" 424 425 const ( 426 c0 = iota 427 c1 = iota 428 c2 = iota 429 ) 430 func main() { 431 fmt.Println(c0, c1, c2) //Print : 0 1 2 432 } 433 \end{Go} 434 You can avoid writing successive iota in front of every constant. This can be simplified as in the below code listing: 435 \begin{Go} 436 package main 437 438 import "fmt" 439 440 const ( 441 c0 = iota 442 c1 443 c2 444 ) 445 446 func main() { 447 fmt.Println(c0, c1, c2) //Print : 0 1 2 448 } 449 \end{Go} 450 To start a list of constants at 1 instead of 0, you can use iota in an arithmetic expression. 451 \begin{Go} 452 package main 453 454 import "fmt" 455 456 const ( 457 c0 = iota + 1 458 c1 459 c2 460 ) 461 462 func main() { 463 fmt.Println(c0, c1, c2) // Print : 1 2 3 464 } 465 \end{Go} 466 You can use the blank identifier to skip a value in a list of constants. 467 \begin{Go} 468 package main 469 470 import "fmt" 471 472 const ( 473 c1 = iota + 1 474 _ 475 c3 476 c4 477 ) 478 479 func main() { 480 fmt.Println(c1, c3, c4) // Print : 1 3 4 481 } 482 \end{Go} 483 484 613 485 \section{Java} 614 486 … … 617 489 \section{Rust} 618 490 491 619 492 \section{Swift} 620 493 494 \lstnewenvironment{swift}[1][]{% necessary 495 \lstset{ 496 language=Swift, 497 escapechar=\$, % LaTeX escape in CFA code 498 moredelim=**[is][\color{red}]{@}{@}, % red highlighting @...@ 499 }% lstset 500 \lstset{#1}% necessary 501 }{} 502 503 Model custom types that define a list of possible values. 504 505 An 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. 506 507 If you are familiar with C, you will know that C enumerations assign related names to a set of integer values. 508 Enumerations in Swift are much more flexible, and don't have to provide a value for each case of the enumeration. 509 If 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. 510 511 Alternatively, 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. 512 You 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. 513 514 Enumerations in Swift are first-class types in their own right. 515 They 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. 516 Enumerations can also define initializers to provide an initial case value; 517 can be extended to expand their functionality beyond their original implementation; and can conform to protocols to provide standard functionality. 518 519 For more about these capabilities, see Properties, Methods, Initialization, Extensions, and Protocols. 520 521 \paragraph{Enumeration Syntax} 522 523 You introduce enumerations with the @enum@ keyword and place their entire definition within a pair of braces: 524 \begin{swift} 525 enum SomeEnumeration { 526 // enumeration definition goes here 527 } 528 \end{swift} 529 Here's an example for the four main points of a compass: 530 \begin{swift} 531 enum CompassPoint { 532 case north 533 case south 534 case east 535 case west 536 } 537 \end{swift} 538 The values defined in an enumeration (such as @north@, @south@, @east@, and @west@) are its enumeration cases. 539 You use the @case@ keyword to introduce new enumeration cases. 540 541 Note: 542 Swift enumeration cases don't have an integer value set by default, unlike languages like C and Objective-C. 543 In the CompassPoint example above, @north@, @south@, @east@ and @west@ don't implicitly equal 0, 1, 2 and 3. 544 Instead, the different enumeration cases are values in their own right, with an explicitly defined type of CompassPoint. 545 546 Multiple cases can appear on a single line, separated by commas: 547 \begin{swift} 548 enum Planet { 549 case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune 550 } 551 \end{swift} 552 Each enumeration definition defines a new type. 553 Like other types in Swift, their names (such as @CompassPoint@ and @Planet@) start with a capital letter. 554 Give enumeration types singular rather than plural names, so that they read as self-evident: 555 \begin{swift} 556 var directionToHead = CompassPoint.west 557 \end{swift} 558 The type of @directionToHead@ is inferred when it's initialized with one of the possible values of @CompassPoint@. 559 Once @directionToHead@ is declared as a @CompassPoint@, you can set it to a different @CompassPoint@ value using a shorter dot syntax: 560 \begin{swift} 561 directionToHead = .east 562 \end{swift} 563 The type of @directionToHead@ is already known, and so you can drop the type when setting its value. 564 This makes for highly readable code when working with explicitly typed enumeration values. 565 566 \paragraph{Matching Enumeration Values with a Switch Statement} 567 568 You can match individual enumeration values with a switch statement: 569 \begin{swift} 570 directionToHead = .south 571 switch directionToHead { 572 case .north: 573 print("Lots of planets have a north") 574 case .south: 575 print("Watch out for penguins") 576 case .east: 577 print("Where the sun rises") 578 case .west: 579 print("Where the skies are blue") 580 } 581 // Prints "Watch out for penguins" 582 \end{swift} 583 You can read this code as: 584 \begin{quote} 585 "Consider the value of directionToHead. 586 In the case where it equals @.north@, print "Lots of planets have a north". 587 In the case where it equals @.south@, print "Watch out for penguins"." 588 589 ...and so on. 590 \end{quote} 591 As described in Control Flow, a switch statement must be exhaustive when considering an enumeration's cases. 592 If the case for @.west@ is omitted, this code doesn't compile, because it doesn't consider the complete list of @CompassPoint@ cases. 593 Requiring exhaustiveness ensures that enumeration cases aren't accidentally omitted. 594 595 When 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: 596 \begin{swift} 597 let somePlanet = Planet.earth 598 switch somePlanet { 599 case .earth: 600 print("Mostly harmless") 601 default: 602 print("Not a safe place for humans") 603 } 604 // Prints "Mostly harmless" 605 \end{swift} 606 607 \paragraph{Iterating over Enumeration Cases} 608 609 For some enumerations, it's useful to have a collection of all of that enumeration's cases. 610 You enable this by writing @CaseIterable@ after the enumeration's name. 611 Swift exposes a collection of all the cases as an allCases property of the enumeration type. 612 Here's an example: 613 \begin{swift} 614 enum Beverage: CaseIterable { 615 case coffee, tea, juice 616 } 617 let numberOfChoices = Beverage.allCases.count 618 print("\(numberOfChoices) beverages available") 619 // Prints "3 beverages available" 620 \end{swift} 621 In the example above, you write @Beverage.allCases@ to access a collection that contains all of the cases of the @Beverage@ enumeration. 622 You 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. 623 The example above counts how many cases there are, and the example below uses a for-in loop to iterate over all the cases. 624 \begin{swift} 625 for beverage in Beverage.allCases { 626 print(beverage) 627 } 628 // coffee 629 // tea 630 // juice 631 \end{swift} 632 The syntax used in the examples above marks the enumeration as conforming to the @CaseIterable@ protocol. 633 For information about protocols, see Protocols. 634 635 \paragraph{Associated Values} 636 The examples in the previous section show how the cases of an enumeration are a defined (and typed) value in their own right. 637 You can set a constant or variable to Planet.earth, and check for this value later. 638 However, it's sometimes useful to be able to store values of other types alongside these case values. 639 This additional information is called an associated value, and it varies each time you use that case as a value in your code. 640 641 You 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. 642 Enumerations similar to these are known as discriminated unions, tagged unions, or variants in other programming languages. 643 644 For example, suppose an inventory tracking system needs to track products by two different types of barcode. 645 Some products are labeled with 1D barcodes in UPC format, which uses the numbers 0 to 9. 646 Each barcode has a number system digit, followed by five manufacturer code digits and five product code digits. 647 These are followed by a check digit to verify that the code has been scanned correctly: 648 649 Other 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: 650 651 It'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. 652 653 In Swift, an enumeration to define product barcodes of either type might look like this: 654 \begin{swift} 655 enum Barcode { 656 case upc(Int, Int, Int, Int) 657 case qrCode(String) 658 } 659 \end{swift} 660 This can be read as: 661 \begin{quote} 662 "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@." 663 \end{quote} 664 This 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@. 665 666 You can then create new barcodes using either type: 667 \begin{swift} 668 var productBarcode = Barcode.upc(8, 85909, 51226, 3) 669 \end{swift} 670 This 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)@. 671 672 You can assign the same product a different type of barcode: 673 \begin{swift} 674 productBarcode = .qrCode("ABCDEFGHIJKLMNOP") 675 \end{swift} 676 At this point, the original @Barcode.upc@ and its integer values are replaced by the new @Barcode.qrCode@ and its string value. 677 Constants 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. 678 679 You can check the different barcode types using a switch statement, similar to the example in Matching Enumeration Values with a Switch Statement. 680 This time, however, the associated values are extracted as part of the switch statement. 681 You 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: 682 \begin{swift} 683 switch productBarcode { 684 case .upc(let numberSystem, let manufacturer, let product, let check): 685 print("UPC: \(numberSystem), \(manufacturer), \(product), \(check).") 686 case .qrCode(let productCode): 687 print("QR code: \(productCode).") 688 } 689 // Prints "QR code: ABCDEFGHIJKLMNOP." 690 \end{swift} 691 If 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: 692 \begin{swift} 693 switch productBarcode { 694 case let .upc(numberSystem, manufacturer, product, check): 695 print("UPC : \(numberSystem), \(manufacturer), \(product), \(check).") 696 case let .qrCode(productCode): 697 print("QR code: \(productCode).") 698 } 699 // Prints "QR code: ABCDEFGHIJKLMNOP." 700 \end{swift} 701 702 \paragraph{Raw Values} 703 704 The barcode example in Associated Values shows how cases of an enumeration can declare that they store associated values of different types. 705 As an alternative to associated values, enumeration cases can come prepopulated with default values (called raw values), which are all of the same type. 706 707 Here's an example that stores raw ASCII values alongside named enumeration cases: 708 \begin{swift} 709 enum ASCIIControlCharacter: Character { 710 case tab = "\t" 711 case lineFeed = "\n" 712 case carriageReturn = "\r" 713 } 714 \end{swift} 715 Here, 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. 716 Character values are described in Strings and Characters. 717 718 Raw values can be strings, characters, or any of the integer or floating-point number types. 719 Each raw value must be unique within its enumeration declaration. 720 721 Note 722 723 Raw values are not the same as associated values. 724 Raw values are set to prepopulated values when you first define the enumeration in your code, like the three ASCII codes above. 725 The raw value for a particular enumeration case is always the same. 726 Associated 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. 727 Implicitly Assigned Raw Values 728 729 When 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. 730 When you don't, Swift automatically assigns the values for you. 731 732 For example, when integers are used for raw values, the implicit value for each case is one more than the previous case. 733 If the first case doesn't have a value set, its value is 0. 734 735 The enumeration below is a refinement of the earlier Planet enumeration, with integer raw values to represent each planet's order from the sun: 736 737 \begin{swift} 738 enum Planet: Int { 739 case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune 740 } 741 \end{swift} 742 In the example above, Planet.mercury has an explicit raw value of 1, Planet.venus has an implicit raw value of 2, and so on. 743 744 When strings are used for raw values, the implicit value for each case is the text of that case's name. 745 746 The enumeration below is a refinement of the earlier CompassPoint enumeration, with string raw values to represent each direction's name: 747 \begin{swift} 748 enum CompassPoint: String { 749 case north, south, east, west 750 } 751 \end{swift} 752 In the example above, CompassPoint.south has an implicit raw value of "south", and so on. 753 754 You access the raw value of an enumeration case with its rawValue property: 755 \begin{swift} 756 let earthsOrder = Planet.earth.rawValue 757 // earthsOrder is 3 758 759 let sunsetDirection = CompassPoint.west.rawValue 760 // sunsetDirection is "west" 761 \end{swift} 762 763 \paragraph{Initializing from a Raw Value} 764 765 If 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. 766 You can use this initializer to try to create a new instance of the enumeration. 767 768 This example identifies Uranus from its raw value of 7: 769 \begin{swift} 770 let possiblePlanet = Planet(rawValue: 7) 771 // possiblePlanet is of type Planet? and equals Planet.uranus 772 \end{swift} 773 Not all possible Int values will find a matching planet, however. 774 Because of this, the raw value initializer always returns an optional enumeration case. 775 In the example above, possiblePlanet is of type Planet?, or "optional Planet." 776 Note 777 778 The raw value initializer is a failable initializer, because not every raw value will return an enumeration case. 779 For more information, see Failable Initializers. 780 781 If you try to find a planet with a position of 11, the optional Planet value returned by the raw value initializer will be nil: 782 \begin{swift} 783 let positionToFind = 11 784 if let somePlanet = Planet(rawValue: positionToFind) { 785 switch somePlanet { 786 case .earth: 787 print("Mostly harmless") 788 default: 789 print("Not a safe place for humans") 790 } 791 } else { 792 print("There isn't a planet at position \(positionToFind)") 793 } 794 // Prints "There isn't a planet at position 11" 795 \end{swift} 796 This example uses optional binding to try to access a planet with a raw value of 11. 797 The 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. 798 In this case, it isn't possible to retrieve a planet with a position of 11, and so the else branch is executed instead. 799 800 \paragraph{Recursive Enumerations} 801 802 A recursive enumeration is an enumeration that has another instance of the enumeration as the associated value for one or more of the enumeration cases. 803 You indicate that an enumeration case is recursive by writing indirect before it, which tells the compiler to insert the necessary layer of indirection. 804 805 For example, here is an enumeration that stores simple arithmetic expressions: 806 \begin{swift} 807 enum ArithmeticExpression { 808 case number(Int) 809 indirect case addition(ArithmeticExpression, ArithmeticExpression) 810 indirect case multiplication(ArithmeticExpression, ArithmeticExpression) 811 } 812 \end{swift} 813 You 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: 814 \begin{swift} 815 indirect enum ArithmeticExpression { 816 case number(Int) 817 case addition(ArithmeticExpression, ArithmeticExpression) 818 case multiplication(ArithmeticExpression, ArithmeticExpression) 819 } 820 \end{swift} 821 This enumeration can store three kinds of arithmetic expressions: a plain number, the addition of two expressions, and the multiplication of two expressions. 822 The addition and multiplication cases have associated values that are also arithmetic expressions -- these associated values make it possible to nest expressions. 823 For 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. 824 Because the data is nested, the enumeration used to store the data also needs to support nesting -- this means the enumeration needs to be recursive. 825 The code below shows the ArithmeticExpression recursive enumeration being created for (5 + 4) * 2: 826 \begin{swift} 827 let five = ArithmeticExpression.number(5) 828 let four = ArithmeticExpression.number(4) 829 let sum = ArithmeticExpression.addition(five, four) 830 let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2)) 831 \end{swift} 832 A recursive function is a straightforward way to work with data that has a recursive structure. 833 For example, here's a function that evaluates an arithmetic expression: 834 \begin{swift} 835 func evaluate(_ expression: ArithmeticExpression) -> Int { 836 switch expression { 837 case let .number(value): 838 return value 839 case let .addition(left, right): 840 return evaluate(left) + evaluate(right) 841 case let .multiplication(left, right): 842 return evaluate(left) * evaluate(right) 843 } 844 } 845 846 print(evaluate(product)) 847 // Prints "18" 848 \end{swift} 849 This function evaluates a plain number by simply returning the associated value. 850 It 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. 851 852 621 853 \section{Python} 622 854
Note: See TracChangeset
for help on using the changeset viewer.