diff --git a/source/chapter2/02_Basic_Operators.md b/source/chapter2/02_Basic_Operators.md index e95c48fa..d034f68b 100755 --- a/source/chapter2/02_Basic_Operators.md +++ b/source/chapter2/02_Basic_Operators.md @@ -6,46 +6,49 @@ > 校对:[EvilCome](https://github.com/Evilcome) > 2.0 -> 翻译+校对:[JackAlan](https://github.com/AlanMelody) - +> 翻译+校对:[JackAlan](https://github.com/AlanMelody) + > 2.1 > 校对:[shanks](http://codebuild.me) +> 2.2 +> 翻译+校对:[Cee](https://github.com/Cee) + 本页包含内容: - [术语](#terminology) - [赋值运算符](#assignment_operator) - [算术运算符](#arithmetic_operators) -- [组合赋值运算符(Compound Assignment Operators)](#compound_assignment_operators) +- [组合赋值运算符](#compound_assignment_operators) - [比较运算符](#comparison_operators) -- [三目运算符(Ternary Conditional Operator)](#ternary_conditional_operator) +- [三目运算符](#ternary_conditional_operator) - [空合运算符](#nil_coalescing_operator) - [区间运算符](#range_operators) - [逻辑运算符](#logical_operators) -运算符是检查、改变、合并值的特殊符号或短语。例如,加号`+`将两个数相加(如`let i = 1 + 2`)。更复杂的运算例子包括逻辑与运算符`&&`(如`if enteredDoorCode && passedRetinaScan`),或让 i 值加1的便捷自增运算符`++i`等。 +运算符是检查、改变、合并值的特殊符号或短语。例如,加号(`+`)将两个数相加(如 `let i = 1 + 2`)。更复杂的运算例子包括逻辑与运算符 `&&`(如 `if enteredDoorCode && passedRetinaScan`),或让 i 值加 1 的便捷自增运算符 `++i` 等。 Swift 支持大部分标准 C 语言的运算符,且改进许多特性来减少常规编码错误。如:赋值符(`=`)不返回值,以防止把想要判断相等运算符(`==`)的地方写成赋值符导致的错误。算术运算符(`+`,`-`,`*`,`/`,`%`等)会检测并不允许值溢出,以此来避免保存变量时由于变量大于或小于其类型所能承载的范围时导致的异常结果。当然允许你使用 Swift 的溢出运算符来实现溢出。详情参见[溢出运算符](../chapter2/25_Advanced_Operators.html#overflow_operators)。 -区别于 C 语言,在 Swift 中你可以对浮点数进行取余运算(`%`),Swift 还提供了 C 语言没有的表达两数之间的值的区间运算符(`a.. ## 术语 -运算符有一元、二元和三元运算符。 +运算符分为一元、二元和三元运算符。 -- 一元运算符对单一操作对象操作(如`-a`)。一元运算符分前置运算符和后置运算符,前置运算符需紧跟在操作对象之前(如`!b`),后置运算符需紧跟在操作对象之后(如`i++`)。 -- 二元运算符操作两个操作对象(如`2 + 3`),是中置的,因为它们出现在两个操作对象之间。 +- 一元运算符对单一操作对象操作(如 `-a`)。一元运算符分前置运算符和后置运算符,前置运算符需紧跟在操作对象之前(如 `!b`),后置运算符需紧跟在操作对象之后(如 `i++`)。 +- 二元运算符操作两个操作对象(如 `2 + 3`),是中置的,因为它们出现在两个操作对象之间。 - 三元运算符操作三个操作对象,和 C 语言一样,Swift 只有一个三元运算符,就是三目运算符(`a ? b : c`)。 -受运算符影响的值叫操作数,在表达式`1 + 2`中,加号`+`是二元运算符,它的两个操作数是值`1`和`2`。 +受运算符影响的值叫操作数,在表达式 `1 + 2` 中,加号 `+` 是二元运算符,它的两个操作数是值 `1` 和 `2`。 ## 赋值运算符 -赋值运算(`a = b`),表示用`b`的值来初始化或更新`a`的值: +赋值运算(`a = b`),表示用 `b` 的值来初始化或更新 `a` 的值: ```swift let b = 10 @@ -58,7 +61,7 @@ a = b ```swift let (x, y) = (1, 2) -// 现在 x 等于 1, y 等于 2 +// 现在 x 等于 1,y 等于 2 ``` 与 C 语言和 Objective-C 不同,Swift 的赋值操作并不返回任何值。所以以下代码是错误的: @@ -69,7 +72,7 @@ if x = y { } ``` -这个特性使你无法把(`==`)错写成(`=`),由于`if x = y`是错误代码,Swift帮你避免此类错误的的发生。 +这个特性使你无法把(`==`)错写成(`=`),由于 `if x = y` 是错误代码,Swift 能帮你避免此类错误发生。 ## 算术运算符 @@ -88,9 +91,9 @@ Swift 中所有数值类型都支持了基本的四则算术运算: 10.0 / 2.5 // 等于 4.0 ``` -与 C 语言和 Objective-C 不同的是,Swift 默认情况下不允许在数值运算中出现溢出情况。但是你可以使用 Swift 的溢出运算符来实现溢出运算(如`a &+ b`)。详情参见[溢出运算符](../chapter2/25_Advanced_Operators.html#overflow_operators)。 +与 C 语言和 Objective-C 不同的是,Swift 默认情况下不允许在数值运算中出现溢出情况。但是你可以使用 Swift 的溢出运算符来实现溢出运算(如 `a &+ b`)。详情参见[溢出运算符](../chapter2/25_Advanced_Operators.html#overflow_operators)。 -加法运算符也可用于`String`的拼接: +加法运算符也可用于 `String` 的拼接: ```swift "hello, " + "world" // 等于 "hello, world" @@ -98,16 +101,16 @@ Swift 中所有数值类型都支持了基本的四则算术运算: ### 求余运算符 -求余运算(`a % b`)是计算`b`的多少倍刚刚好可以容入`a`,返回多出来的那部分(余数)。 +求余运算(`a % b`)是计算 `b` 的多少倍刚刚好可以容入`a`,返回多出来的那部分(余数)。 ->注意: -求余运算(`%`)在其他语言也叫取模运算。然而严格说来,我们看该运算符对负数的操作结果,"求余"比"取模"更合适些。 +> 注意: +求余运算(`%`)在其他语言也叫取模运算。然而严格说来,我们看该运算符对负数的操作结果,「求余」比「取模」更合适些。 -我们来谈谈取余是怎么回事,计算`9 % 4`,你先计算出`4`的多少倍会刚好可以容入`9`中: +我们来谈谈取余是怎么回事,计算 `9 % 4`,你先计算出 `4` 的多少倍会刚好可以容入 `9` 中: ![Art/remainderInteger_2x.png](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/remainderInteger_2x.png "Art/remainderInteger_2x.png") -2倍,非常好,那余数是1(用橙色标出) +你可以在 `9` 中放入两个 `4`,那余数是 1(用橙色标出)。 在 Swift 中可以表达为: @@ -115,13 +118,13 @@ Swift 中所有数值类型都支持了基本的四则算术运算: 9 % 4 // 等于 1 ``` -为了得到`a % b`的结果,`%`计算了以下等式,并输出`余数`作为结果: +为了得到 `a % b` 的结果,`%` 计算了以下等式,并输出`余数`作为结果: a = (b × 倍数) + 余数 -当`倍数`取最大值的时候,就会刚好可以容入`a`中。 +当`倍数`取最大值的时候,就会刚好可以容入 `a` 中。 -把`9`和`4`代入等式中,我们得`1`: +把 `9` 和 `4` 代入等式中,我们得 `1`: 9 = (4 × 2) + 1 @@ -131,13 +134,13 @@ Swift 中所有数值类型都支持了基本的四则算术运算: -9 % 4 // 等于 -1 ``` -把`-9`和`4`代入等式,`-2`是取到的最大整数: +把 `-9` 和 `4` 代入等式,`-2` 是取到的最大整数: -9 = (4 × -2) + -1 -余数是`-1`。 +余数是 `-1`。 -在对负数`b`求余时,`b`的符号会被忽略。这意味着 `a % b` 和 `a % -b`的结果是相同的。 +在对负数 `b` 求余时,`b` 的符号会被忽略。这意味着 `a % b` 和 `a % -b` 的结果是相同的。 ### 浮点数求余计算 @@ -147,27 +150,27 @@ Swift 中所有数值类型都支持了基本的四则算术运算: 8 % 2.5 // 等于 0.5 ``` -这个例子中,`8`除于`2.5`等于`3`余`0.5`,所以结果是一个`Double`值`0.5`。 +这个例子中,`8` 除以 `2.5` 等于 `3` 余 `0.5`,所以结果是一个 `Double` 型的值为 `0.5`。 ![Art/remainderFloat_2x.png](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/remainderFloat_2x.png "Art/remainderFloat_2x.png") ### 自增和自减运算 -和 C 语言一样,Swift 也提供了对变量本身加1或减1的自增(`++`)和自减(`--`)的缩略算符。其操作对象可以是整形和浮点型。 +和 C 语言一样,Swift 也提供了对变量本身加 1 或减 1 的自增(`++`)和自减(`--`)的缩略算符。其操作对象可以是整形和浮点型。 ```swift var i = 0 ++i // 现在 i = 1 ``` -每调用一次`++i`,`i`的值就会加1。实际上,`++i`是`i = i + 1`的简写,而`--i`是`i = i - 1`的简写。 +每调用一次 `++i`,`i` 的值就会加 1。实际上,`++i` 是 `i = i + 1` 的简写,而 `--i` 是 `i = i - 1` 的简写。 -`++`和`--`既可以用作前置运算又可以用作后置运算。`++i`,`i++`,`--i`和`i--`都是有效的写法。 +`++` 和 `--` 既可以用作前置运算又可以用作后置运算。`++i`、`i++` 都是有效的自增的写法;相类似对应自减的写法则是 `--i` 和 `i--`。 -我们需要注意的是这些运算符即可修改了`i`的值也可以返回`i`的值。如果你只想修改`i`的值,那你就可以忽略这个返回值。但如果你想使用返回值,你就需要留意前置和后置操作的返回值是不同的,她们遵循以下原则: +我们需要注意的是这些运算符即可修改了 `i` 的值也可以返回 `i` 的值。如果你只想修改 `i` 的值,那你就可以忽略这个返回值。但如果你想使用返回值,你就需要留意前置和后置操作的返回值是不同的,它们遵循以下原则: -- 当`++`前置的时候,先自増再返回。 -- 当`++`后置的时候,先返回再自增。 +- 当 `++` 前置的时候,先自増再返回。 +- 当 `++` 后置的时候,先返回再自增。 例如: @@ -177,16 +180,16 @@ let b = ++a // a 和 b 现在都是 1 let c = a++ // a 现在 2, 但 c 是 a 自增前的值 1 ``` -上述例子,`let b = ++a`先把`a`加1了再返回`a`的值。所以`a`和`b`都是新值`1`。 +上述例子,`let b = ++a` 先把 `a` 加 1 了再返回 `a` 的值。所以 `a` 和 `b` 都是新值 `1`。 -而`let c = a++`,是先返回了`a`的值,然后`a`才加1。所以`c`得到了`a`的旧值1,而`a`加1后变成2。 +而 `let c = a++`,是先返回了 `a` 的值,然后 `a` 才加 1。所以 `c` 得到了 `a` 的旧值 1,而 `a` 加 1 后变成 2。 -除非你需要使用`i++`的特性,不然推荐你使用`++i`和`--i`,因为先修改后返回这样的行为更符合我们的逻辑。 +除非你需要使用 `i++` 的特性,不然推荐你使用 `++i` 和 `--i`,因为先修改后返回这样的行为更符合我们的逻辑。 ### 一元负号运算符 -数值的正负号可以使用前缀`-`(即一元负号)来切换: +数值的正负号可以使用前缀 `-`(即一元负号)来切换: ```swift let three = 3 @@ -205,28 +208,29 @@ let minusSix = -6 let alsoMinusSix = +minusSix // alsoMinusSix 等于 -6 ``` -虽然一元`+`什么都不会改变,但当你在使用一元负号来表达负数时,你可以使用一元正号来表达正数,如此你的代码会具有对称美。 +虽然一元 `+` 什么都不会改变,但当你在使用一元负号来表达负数时,你可以使用一元正号来表达正数,如此你的代码会具有对称美。 -## 组合赋值运算符(Compound Assignment Operators) +## 组合赋值运算符 如同 C 语言,Swift 也提供把其他运算符和赋值运算(`=`)组合的组合赋值运算符,组合加运算(`+=`)是其中一个例子: ```swift var a = 1 -a += 2 // a 现在是 3 +a += 2 +// a 现在是 3 ``` -表达式`a += 2`是`a = a + 2`的简写,一个组合加运算就是把加法运算和赋值运算组合成进一个运算符里,同时完成两个运算任务。 +表达式 `a += 2` 是 `a = a + 2` 的简写,一个组合加运算就是把加法运算和赋值运算组合成进一个运算符里,同时完成两个运算任务。 ->注意: +> 注意: 复合赋值运算没有返回值,`let b = a += 2`这类代码是错误。这不同于上面提到的自增和自减运算符。 在[表达式](../chapter3/04_Expressions.html)章节里有复合运算符的完整列表。 ‌ -## 比较运算符 +## 比较运算符(Comparison Operators) 所有标准 C 语言中的比较运算都可以在 Swift 中使用: @@ -238,7 +242,7 @@ a += 2 // a 现在是 3 - 小于等于(`a <= b`) > 注意: -Swift 也提供恒等`===`和不恒等`!==`这两个比较符来判断两个对象是否引用同一个对象实例。更多细节在[类与结构](../chapter2/09_Classes_and_Structures.html)。 +Swift 也提供恒等(`===`)和不恒等(`!==`)这两个比较符来判断两个对象是否引用同一个对象实例。更多细节在[类与结构](../chapter2/09_Classes_and_Structures.html)。 每个比较运算都返回了一个标识表达式是否成立的布尔值: @@ -263,12 +267,25 @@ if name == "world" { // 输出 "hello, world", 因为 `name` 就是等于 "world" ``` -关于`if`语句,请看[控制流](../chapter2/05_Control_Flow.html)。 +关于 `if` 语句,请看[控制流](../chapter2/05_Control_Flow.html)。 + +当元组中的值可以比较时,你也可以使用这些运算符来比较它们的大小。例如,因为 `Int` 和 `String` 类型的值可以比较,所以类型为 `(Int, String)` 的元组也可以被比较。相反,`Bool` 不能被比较,也意味着存有布尔类型的元组不能被比较。 + +比较元组大小会按照从左到右、逐值比较的方式,直到发现有两个值不等时停止。如果所有的值都相等,那么这一对元组我们就称它们是相等的。例如: + +```swift +(1, "zebra") < (2, "apple") // true,因为 1 小于 2 +(3, "apple") < (3, "bird") // true,因为 3 等于 3,但是 apple 小于 bird +(4, "dog") == (4, "dog") // true,因为 4 等于 4,dog 等于 dog +``` + +> 注意: +Swift 标准库只能比较七个以内元素的元组比较函数。如果你的元组元素超过七个时,你需要自己实现比较运算符。 -## 三目运算符(Ternary Conditional Operator) +## 三目运算符(Ternary Conditional Operator) -三目运算符的特殊在于它是有三个操作数的运算符,它的原型是 `问题 ? 答案1 : 答案2`。它简洁地表达根据`问题`成立与否作出二选一的操作。如果`问题`成立,返回`答案1`的结果; 如果不成立,返回`答案2`的结果。 +三目运算符的特殊在于它是有三个操作数的运算符,它的形式是 `问题 ? 答案 1 : 答案 2`。它简洁地表达根据 `问题`成立与否作出二选一的操作。如果 `问题` 成立,返回 `答案 1` 的结果;反之返回 `答案 2` 的结果。 三目运算符是以下代码的缩写形式: @@ -280,7 +297,7 @@ if question { } ``` -这里有个计算表格行高的例子。如果有表头,那行高应比内容高度要高出50点;如果没有表头,只需高出20点: +这里有个计算表格行高的例子。如果有表头,那行高应比内容高度要高出 50 点;如果没有表头,只需高出 20 点: ```swift let contentHeight = 40 @@ -303,28 +320,25 @@ if hasHeader { // rowHeight 现在是 90 ``` -第一段代码例子使用了三目运算,所以一行代码就能让我们得到正确答案。这比第二段代码简洁得多,无需将`rowHeight`定义成变量,因为它的值无需在`if`语句中改变。 +第一段代码例子使用了三目运算,所以一行代码就能让我们得到正确答案。这比第二段代码简洁得多,无需将 `rowHeight` 定义成变量,因为它的值无需在 `if` 语句中改变。 三目运算提供有效率且便捷的方式来表达二选一的选择。需要注意的事,过度使用三目运算符会使简洁的代码变的难懂。我们应避免在一个组合语句中使用多个三目运算符。 -## 空合运算符(Nil Coalescing Operator) +## 空合运算符(Nil Coalescing Operator) -空合运算符(`a ?? b`)将对可选类型`a`进行空判断,如果`a`包含一个值就进行解封,否则就返回一个默认值`b`.这个运算符有两个条件: +空合运算符(`a ?? b`)将对可选类型 `a` 进行空判断,如果 `a` 包含一个值就进行解封,否则就返回一个默认值 `b`。表达式 `a` 必须是 Optional 类型。默认值 `b` 的类型必须要和 `a` 存储值的类型保持一致。 -- 表达式`a`必须是Optional类型 -- 默认值`b`的类型必须要和`a`存储值的类型保持一致 - -空合运算符是对以下代码的简短表达方法 +空合运算符是对以下代码的简短表达方法: ```swift a != nil ? a! : b ``` -上述代码使用了三目运算符。当可选类型`a`的值不为空时,进行强制解封(`a!`)访问`a`中值,反之当`a`中值为空时,返回默认值b。无疑空合运算符(`??`)提供了一种更为优雅的方式去封装条件判断和解封两种行为,显得简洁以及更具可读性。 +上述代码使用了三目运算符。当可选类型 `a` 的值不为空时,进行强制解封(`a!`),访问 `a` 中的值;反之返回默认值 `b`。无疑空合运算符(`??`)提供了一种更为优雅的方式去封装条件判断和解封两种行为,显得简洁以及更具可读性。 > 注意: -如果`a`为非空值(`non-nil`),那么值`b`将不会被估值。这也就是所谓的短路求值。 +如果 `a` 为非空值(`non-nil`),那么值 `b` 将不会被计算。这也就是所谓的短路求值。 下文例子采用空合运算符,实现了在默认颜色名和可选自定义颜色名之间抉择: @@ -336,10 +350,10 @@ var colorNameToUse = userDefinedColorName ?? defaultColorName // userDefinedColorName 的值为空,所以 colorNameToUse 的值为 "red" ``` -`userDefinedColorName`变量被定义为一个可选`String`类型,默认值为`nil`。由于`userDefinedColorName`是一个可选类型,我们可以使用空合运算符去判断其值。在上一个例子中,通过空合运算符为一个名为`colorNameToUse`的变量赋予一个字符串类型初始值。 -由于`userDefinedColorName`值为空,因此表达式`userDefinedColorName ?? defaultColorName`返回`defaultColorName`的值,即`red`。 +`userDefinedColorName` 变量被定义为一个可选的 `String` 类型,默认值为 `nil`。由于 `userDefinedColorName` 是一个可选类型,我们可以使用空合运算符去判断其值。在上一个例子中,通过空合运算符为一个名为 `colorNameToUse` 的变量赋予一个字符串类型初始值。 +由于 `userDefinedColorName` 值为空,因此表达式 `userDefinedColorName ?? defaultColorName` 返回 `defaultColorName` 的值,即 `red`。 -另一种情况,分配一个非空值(`non-nil`)给`userDefinedColorName`,再次执行空合运算,运算结果为封包在`userDefaultColorName`中的值,而非默认值。 +另一种情况,分配一个非空值(`non-nil`)给 `userDefinedColorName`,再次执行空合运算,运算结果为封包在 `userDefaultColorName` 中的值,而非默认值。 ```swift userDefinedColorName = "green" @@ -348,14 +362,14 @@ colorNameToUse = userDefinedColorName ?? defaultColorName ``` -## 区间运算符 +## 区间运算符(Range Operators) Swift 提供了两个方便表达一个区间的值的运算符。 ### 闭区间运算符 -闭区间运算符(`a...b`)定义一个包含从`a`到`b`(包括`a`和`b`)的所有值的区间,`b`必须大于等于`a`。 +闭区间运算符(`a...b`)定义一个包含从 `a` 到 `b`(包括 `a` 和 `b`)的所有值的区间。`a` 的值不能超过 `b`。 ‌ -闭区间运算符在迭代一个区间的所有值时是非常有用的,如在`for-in`循环中: +闭区间运算符在迭代一个区间的所有值时是非常有用的,如在 `for-in` 循环中: ```swift for index in 1...5 { @@ -368,14 +382,14 @@ for index in 1...5 { // 5 * 5 = 25 ``` -关于`for-in`,请看[控制流](../chapter2/05_Control_Flow.html)。 +关于 `for-in`,请看[控制流](../chapter2/05_Control_Flow.html)。 ### 半开区间运算符 -半开区间(`a.. -## 逻辑运算 +## 逻辑运算(Logical Operators) 逻辑运算的操作对象是逻辑布尔值。Swift 支持基于 C 语言的三个标准逻辑运算。 @@ -402,9 +416,9 @@ for i in 0..注意: -Swift 逻辑操作符`&&`和`||`是左结合的,这意味着拥有多元逻辑操作符的复合表达式优先计算最左边的子表达式。 +> 注意: +Swift 逻辑操作符 `&&` 和 `||` 是左结合的,这意味着拥有多元逻辑操作符的复合表达式优先计算最左边的子表达式。 ### 使用括号来明确优先级