From 462219eda63983907055c97e4d7ae243abb403fd Mon Sep 17 00:00:00 2001 From: futantan Date: Thu, 30 Jul 2015 17:00:16 +0800 Subject: [PATCH 1/3] =?UTF-8?q?2015-07-21=20=E5=BC=80=E5=A7=8B=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=20=EF=BC=8D=20=E6=B7=BB=E5=8A=A0Recursive=20Enumerati?= =?UTF-8?q?ons?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/chapter2/08_Enumerations.md | 58 ++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/source/chapter2/08_Enumerations.md b/source/chapter2/08_Enumerations.md index 1484694f..45431733 100755 --- a/source/chapter2/08_Enumerations.md +++ b/source/chapter2/08_Enumerations.md @@ -10,6 +10,7 @@ - [匹配枚举值与`Swith`语句(Matching Enumeration Values with a Switch Statement)](#matching_enumeration_values_with_a_switch_statement) - [相关值(Associated Values)](#associated_values) - [原始值(Raw Values)](#raw_values) +- [递归枚举(Recursive Enumerations)](#recursive_enumerations) 枚举定义了一个通用类型的一组相关的值,使你可以在你的代码中以一个安全的方式来使用这些值。 @@ -249,3 +250,60 @@ if let somePlanet = Planet(rawValue: positionToFind) { 这个范例使用可选绑定(optional binding),通过原始值`9`试图访问一个行星。`if let somePlanet = Planet(rawValue: 9)`语句获得一个可选`Planet`,如果可选`Planet`可以被获得,把`somePlanet`设置成该可选`Planet`的内容。在这个范例中,无法检索到位置为`9`的行星,所以`else`分支被执行。 + +## 递归枚举(Recursive Enumerations) + +Enumerations work well for modeling data when there is a fixed number of possibilities that need to be considered, such as the operations used for doing simple integer arithmetic. These operations let you combine simple arithmetic expressions that are made up of integers such as `5` into more complex ones such as `5 + 4`. + +One important characteristic of arithmetic expressions is that they can be nested. 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. 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. + +A recursive enumeration is an enumeration that has another instance of the enumeration as the associated value for one or more of the enumeration members. The compiler has to insert a layer of indirection when it works with recursive enumerations. You indicate that an enumeration member is recursive by writing indirect before it. + +A `recursive enumeration` is an enumeration that has another instance of the enumeration as the associated value for one or more of the enumeration members. The compiler has to insert a layer of indirection when it works with recursive enumerations. You indicate that an enumeration member is recursive by writing `indirect` before it. + +For example, here is an enumeration that stores simple arithmetic expressions: + +```swift +enum ArithmeticExpression { + case Number(Int) + indirect case Addition(ArithmeticExpression, ArithmeticExpression) + indirect case Multiplication(ArithmeticExpression, ArithmeticExpression) +} +``` + +You can also write `indirect` before the beginning of the enumeration, to enable indirection for all of the enumeration’s members that need it: + +```swift +indirect enum ArithmeticExpression { + case Number(Int) + case Addition(ArithmeticExpression, ArithmeticExpression) + case Multiplication(ArithmeticExpression, ArithmeticExpression) +} +``` + +This enumeration can store three kinds of arithmetic expressions: a plain number, the addition of two expressions, and the multiplication of two expressions. The `Addition` and `Multiplication` members have associated values that are also arithmetic expressions—these associated values make it possible to nest expressions. + +A recursive function is a straightforward way to work with data that has a recursive structure. For example, here’s a function that evaluates an arithmetic expression: + +```swift +func evaluate(expression: ArithmeticExpression) -> Int { + switch expression { + case .Number(let value): + return value + case .Addition(let left, let right): + return evaluate(left) + evaluate(right) + case .Multiplication(let left, let right): + return evaluate(left) * evaluate(right) + } +} + +// evaluate (5 + 4) * 2 +let five = ArithmeticExpression.Number(5) +let four = ArithmeticExpression.Number(4) +let sum = ArithmeticExpression.Addition(five, four) +let product = ArithmeticExpression.Multiplication(sum, ArithmeticExpression.Number(2)) +print(evaluate(product)) +// prints "18" +``` + +This function evaluates a plain number by simply returning the associated value. 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. From 4102e73967e6737630c4ed51205aa5e9b39717bb Mon Sep 17 00:00:00 2001 From: futantan Date: Thu, 30 Jul 2015 17:38:17 +0800 Subject: [PATCH 2/3] =?UTF-8?q?2015-07-21=20=E5=AE=8C=E6=88=90=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=20=EF=BC=8D=20=E6=B7=BB=E5=8A=A0Recursive=20Enumerati?= =?UTF-8?q?ons?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/chapter2/08_Enumerations.md | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/source/chapter2/08_Enumerations.md b/source/chapter2/08_Enumerations.md index 45431733..123dc244 100755 --- a/source/chapter2/08_Enumerations.md +++ b/source/chapter2/08_Enumerations.md @@ -253,15 +253,14 @@ if let somePlanet = Planet(rawValue: positionToFind) { ## 递归枚举(Recursive Enumerations) -Enumerations work well for modeling data when there is a fixed number of possibilities that need to be considered, such as the operations used for doing simple integer arithmetic. These operations let you combine simple arithmetic expressions that are made up of integers such as `5` into more complex ones such as `5 + 4`. +在对操作符进行描述的时候,使用枚举类型来对数据建模很方便,因为需要考虑的情况固定可枚举。操作符可以将两个由数字组成的算数表达式连接起来,例如,将`5`连接成复杂一些的表达式`5+4`. -One important characteristic of arithmetic expressions is that they can be nested. 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. 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. +算数表达式的一个重要特性是,表达式可以嵌套使用。例如,表达式`(5 + 4) * 2`乘号右边是一个数字,左边则是另一个表达式。因为数据是嵌套的,因而用来存储数据的枚举类型也许要支持这种嵌套————这表示枚举类型需要支持递归。 -A recursive enumeration is an enumeration that has another instance of the enumeration as the associated value for one or more of the enumeration members. The compiler has to insert a layer of indirection when it works with recursive enumerations. You indicate that an enumeration member is recursive by writing indirect before it. +`递归枚举(recursive enumeration)`是一种枚举类型,表示它的枚举中,有一个或多个枚举成员拥有该枚举的其他成员作为相关值。使用递归枚举时,编译器会插入一个中间层。你可以在枚举成员前加上`indirect`来表示这成员可递归。 -A `recursive enumeration` is an enumeration that has another instance of the enumeration as the associated value for one or more of the enumeration members. The compiler has to insert a layer of indirection when it works with recursive enumerations. You indicate that an enumeration member is recursive by writing `indirect` before it. +例如,下面的例子中,枚举类型存储了简单的算数表达式: -For example, here is an enumeration that stores simple arithmetic expressions: ```swift enum ArithmeticExpression { @@ -271,7 +270,7 @@ enum ArithmeticExpression { } ``` -You can also write `indirect` before the beginning of the enumeration, to enable indirection for all of the enumeration’s members that need it: +你也可以在枚举类型开头加上`indirect`关键字来表示它的所有成员都是可递归的: ```swift indirect enum ArithmeticExpression { @@ -281,9 +280,9 @@ indirect enum ArithmeticExpression { } ``` -This enumeration can store three kinds of arithmetic expressions: a plain number, the addition of two expressions, and the multiplication of two expressions. The `Addition` and `Multiplication` members have associated values that are also arithmetic expressions—these associated values make it possible to nest expressions. +上面定义的枚举类型可以存储三种算数表达式:纯数字、两个表达式的相加、两个表达式相乘。`Addition` 和 `Multiplication`成员的相关值也是算数表达式————这些相关值使得嵌套表达式成为可能。 -A recursive function is a straightforward way to work with data that has a recursive structure. For example, here’s a function that evaluates an arithmetic expression: +递归函数可以很直观地使用具有递归性质的数据结构。例如,下面是一个计算算数表达式的函数: ```swift func evaluate(expression: ArithmeticExpression) -> Int { @@ -297,13 +296,13 @@ func evaluate(expression: ArithmeticExpression) -> Int { } } -// evaluate (5 + 4) * 2 +// 计算 (5 + 4) * 2 let five = ArithmeticExpression.Number(5) let four = ArithmeticExpression.Number(4) let sum = ArithmeticExpression.Addition(five, four) let product = ArithmeticExpression.Multiplication(sum, ArithmeticExpression.Number(2)) print(evaluate(product)) -// prints "18" +// 输出 "18" ``` -This function evaluates a plain number by simply returning the associated value. 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. +该函数如果遇到纯数字,就直接返回该数字的值。如果遇到的是加法或乘法元算,则分别计算左边表达式和右边表达式的值,然后相加或相乘。 From 92ba2e2ef7e61e9599ed5f526d4e2e7b1c374d2d Mon Sep 17 00:00:00 2001 From: futantan Date: Thu, 30 Jul 2015 18:19:33 +0800 Subject: [PATCH 3/3] =?UTF-8?q?2015-07-21=20=E5=AE=8C=E6=88=90=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=20=EF=BC=8D=20Added=20information=20about=20the=20beh?= =?UTF-8?q?avior=20of=20enumeration=20cases=20with=20String=20raw=20values?= =?UTF-8?q?=20to=20the=20Implicitly=20Assigned=20Raw=20Values=20section=20?= =?UTF-8?q?of=20the=20Enumerations=20chapter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/chapter2/08_Enumerations.md | 44 +++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/source/chapter2/08_Enumerations.md b/source/chapter2/08_Enumerations.md index 123dc244..b86e77ae 100755 --- a/source/chapter2/08_Enumerations.md +++ b/source/chapter2/08_Enumerations.md @@ -201,9 +201,16 @@ enum ASCIIControlCharacter: Character { 在这里,称为`ASCIIControlCharacter`的枚举的原始值类型被定义为字符型`Character`,并被设置了一些比较常见的 ASCII 控制字符。字符值的描述请详见字符串和字符[`Strings and Characters`](03_Strings_and_Characters.html)部分。 -注意,原始值和相关值是不相同的。当你开始在你的代码中定义枚举的时候原始值是被预先填充的值,像上述三个 ASCII 码。对于一个特定的枚举成员,它的原始值始终是相同的。相关值是当你在创建一个基于枚举成员的新常量或变量时才会被设置,并且每次当你这么做得时候,它的值可以是不同的。 +原始值可以是字符串,字符,或者任何整型值或浮点型值。每个原始值在它的枚举声明中必须是唯一的。 -原始值可以是字符串,字符,或者任何整型值或浮点型值。每个原始值在它的枚举声明中必须是唯一的。当整型值被用于原始值,如果其他枚举成员没有值时,它们会自动递增。 +>注意: +>原始值和相关值是不相同的。当你开始在你的代码中定义枚举的时候原始值是被预先填充的值,像上述三个 ASCII 码。对于一个特定的枚举成员,它的原始值始终是相同的。相关值是当你在创建一个基于枚举成员的新常量或变量时才会被设置,并且每次当你这么做得时候,它的值可以是不同的。 + +### 原始值的隐式赋值(Implicitly Assigned Raw Values) + +在使用原始值为整数或者字符串类型的枚举时,不需要显式的为每一个成员赋值,这时,Swift将会自动为你赋值。 + +例如,当使用整数作为原始值时,隐式赋值的值依次递增1。如果第一个值没有被赋初值,将会被自动置为0。 下面的枚举是对之前`Planet`这个枚举的一个细化,利用原始整型值来表示每个 planet 在太阳系中的顺序: @@ -213,23 +220,46 @@ enum Planet: Int { } ``` -自动递增意味着`Planet.Venus`的原始值是`2`,依次类推。 +在上面的例子中,`Plant.Mercury`赋了初值`1`,`Planet.Venus`会拥有隐式赋值`2`,依次类推。 + +当使用字符串作为枚举类型的初值时,每个枚举成员的隐式初值则为该成员的名称。 + +下面的例子是`CompassPoint`枚举类型的精简版,使用字符串作为初值类型,隐式初始化为咩个方向的名称: + +```swift +enum CompassPoint: String { + case North, South, East, West +} +``` + +上面例子中,`CompassPoint.South`拥有隐式初值`South`,依次类推。 使用枚举成员的`rawValue`属性可以访问该枚举成员的原始值: ```swift let earthsOrder = Planet.Earth.rawValue -// earthsOrder is 3 +// earthsOrder 值为 3 + +let sunsetDirection = CompassPoint.West.rawValue +// sunsetDirection 值为 "West" ``` -通过参数为`rawValue`构造函数创建特定原始值的枚举。这个例子通过原始值`7`识别`Uranus`: +### 使用原始值初始化枚举变量(Initializing from a Raw Value) + +如果在定义枚举类型的时候使用了原始值,那么将会自动获得一个初始化方法,这个方法将原始值类型作为参数,返回枚举成员或者`nil`。你可以使用这种初始化方法来创建一个新的枚举变量。 + +这个例子通过原始值`7`从而创建枚举成员: ```swift let possiblePlanet = Planet(rawValue: 7) -// possiblePlanet is of type Planet? and equals Planet.Uranus +// possiblePlanet 类型为 Planet? 值为 Planet.Uranus ``` -然而,并非所有可能的`Int`值都可以找到一个匹配的行星。正因为如此,构造函数可以返回一个***可选***的枚举成员。在上面的例子中,`possiblePlanet`是`Planet?`类型,或“可选的`Planet`”。 +然而,并非所有可能的`Int`值都可以找到一个匹配的行星。正因为如此,构造函数可以返回一个*可选*的枚举成员。在上面的例子中,`possiblePlanet`是`Planet?`类型,或“可选的`Planet`”。 + + +>注意: +>原始值构造器是一个可失败构造器,因为并不是每一个原始值都有与之对应的枚举成员。更多信息请参见[Failableinitializers](http://) 如果你试图寻找一个位置为9的行星,通过参数为`rawValue`构造函数返回的可选`Planet`值将是`nil`: