expressions Swift 5.3 beta

This commit is contained in:
Nemocdz
2020-07-01 21:46:15 +08:00
parent 6f2488e19d
commit f5c85a2eed

View File

@ -9,7 +9,6 @@ Swift 中存在四种表达式:前缀表达式,二元表达式,基本表
#### expression {#expression}
> *表达式* → [try 运算符](#try-operator)<sub>可选</sub> [前缀表达式](#prefix-expression) [二元表达式列表](#binary-expressions)<sub>可选</sub>
>
#### expression-list {#expression-list}
@ -232,11 +231,18 @@ f(x as Any)
字面量 | 类型 | 值
:------------- | :---------- | :----------
`#file` | `String` | 所在的文件名
`#file` | `String` | 所在的文件名及模块
`#filePath` | `String` | 所在的文件路径
`#line` | `Int` | 所在的行数
`#column` | `Int` | 所在的列数
`#function` | `String` | 所在的声明的名字
`#dsohandle` | `UnsafeRawPointer` | 所使用的 DSO动态共享对象句柄
`#file` 表达式的值的格式是 *module*/*file**file* 是表达式所在的文件名,*module* 是文件所所在的模块名。`#filePath` 表达式的字符串值是表达式所在的文件在整个文件系统里的路径。所有这些值可以被 `#sourceLocation` 改变,详见 [行控制语句](./05_Statements.md#line-control-statements)。
> 注意
>
> 要解析 `#file` 表达式,第一个斜杠(/)之前的文本作为模块名,最后一个斜杠之后的文本作为文件名。将来,该字符串可能包含多个斜杠,例如 `MyModule/some/disambiguation/MyFile.swift`。
对于 `#function`,在函数中会返回当前函数的名字,在方法中会返回当前方法的名字,在属性的存取器中会返回属性的名字,在特殊的成员如 `init``subscript` 中会返回这个关键字的名字,在某个文件中会返回当前模块的名字。
@ -288,7 +294,7 @@ Xcode 使用 playground 字面量对程序编辑器中的颜色、文件或者
>
> *字面量表达式* → [数组字面量](#array-literal) | [字典字面量](#dictionary-literal) | [练习场字面量](#playground-literal)
>
> *字面量表达式* → **#file** | **#line** | **#column** | **#function**
> *字面量表达式* → **#file** **#filePath** | **#line** | **#column** | **#function**
>
@ -757,7 +763,7 @@ print(count as Any)
// 打印 "Optional(5)"
```
可以混合使用各种 key-path 组件来访问一些深度嵌套类型的值。下面的代码通过组合不同的组件,使用 key-path 表达式访问了一个字典数组中不同的值和属性。
可以混合使用各种 key path 组件来访问一些深度嵌套类型的值。下面的代码通过组合不同的组件,使用 key-path 表达式访问了一个字典数组中不同的值和属性。
```swift
let interestingNumbers = ["prime": [2, 3, 5, 7, 11, 13, 17],
@ -773,6 +779,39 @@ print(interestingNumbers[keyPath: \[String: [Int]].["hexagonal"]!.count.bitWidth
// 打印 "64"
```
你可以在平时提供函数或者闭包的上下文里使用 key path 表达式。特别地,你可以用根类型是 `SomeType` 和路径产生 `Value` 类型值的 key path 表达式来替换类型是 `(SomeType) -> Value` 的函数或者闭包。
```swift
truct Task {
var description: String
var completed: Bool
}
var toDoList = [
Task(description: "Practice ping-pong.", completed: false),
Task(description: "Buy a pirate costume.", completed: true),
Task(description: "Visit Boston in the Fall.", completed: false),
]
// 下面两种写法是等价的。
let descriptions = toDoList.filter(\.completed).map(\.description)
let descriptions2 = toDoList.filter { $0.completed }.map { $0.description }
```
任何 key path 表达式的副作用发生的关键在于表达式在哪里被执行。例如,如果你在 key path 表达式中的一个下标里使用函数调用,该函数只会在表达式计算的时候调用一次,而不是每次这个 key path 被使用的时候。
```swift
func makeIndex() -> Int {
print("Made an index")
return 0
}
// 下面这行调用 makeIndex()。
let taskKeyPath = \[Task][makeIndex()]
// 打印 "Made an index"
// 使用 taskKeyPath 不会再次调用 makeIndex()。
let someTask = toDoList[keyPath: taskKeyPath]
```
关于更多如何使用 key path 与 Objective-C APIs 交互的信息,请参阅 [在 Swift 中使用 Objective-C 运行时特性](https://developer.apple.com/documentation/swift/using_objective_c_runtime_features_in_swift)。关于更多 key-value 编程和 key-value 观察的信息,请参阅 [Key-Value 编程](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/KeyValueCoding/index.html#//apple-ref/doc/uid/10000107i) 和 [Key-Value 观察编程](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html#//apple-ref/doc/uid/10000177i)。
> key-path 表达式语法
@ -959,14 +998,17 @@ print(keyPath == c.getSomeKeyPath())
如果函数声明中指定了参数的名字,那么在调用的时候也必须得写出来。这种函数调用表达式具有以下形式:
> `函数名`(`参数名 1`: `参数 1`, `参数名 2`: `参数 2`)
>
如果函数的最后一个参数是函数类型,可以在函数调用表达式的尾部(右圆括号之后)加上一个闭包,该闭包会作为函数的最后一个参数。如下两种写法是等价的:
```swift
// someFunction 接受整和闭包参
// someFunction 接受整和闭包的实
someFunction(x, f: {$0 == 13})
someFunction(x) {$0 == 13}
// anotherFunction 接受一个整型和两个闭包的实参
anotherFunction(x: x, f: { $0 == 13 }, g: { print(99) })
anotherFunction(x: x) { $0 == 13 } g: { print(99) }
```
如果闭包是该函数的唯一参数,那么圆括号可以省略。
@ -988,30 +1030,32 @@ myData.someMethod {$0 == 13}
>
> *函数调用表达式* → [后缀表达式](#postfix-expression) [函数调用参数子句](#function-call-argument-clause)<sub>可选</sub> [尾随闭包](#trailing-closure)
>
>#### function-call-argument-clause {#function-call-argument-clause}
>
>
#### function-call-argument-clause {#function-call-argument-clause}
>
> *函数调用参数子句* → **(** **)** | **(** [函数调用参数表](#function-call-argument-list) **)**
>
>
#### function-call-argument-list {#function-call-argument-list}
> #### function-call-argument-list {#function-call-argument-list}
>
> *函数调用参数表* → [函数调用参数](#function-call-argument) | [函数调用参数](#function-call-argument) **,** [*函数调用参数表*](#function-call-argument-list)
>
>
#### function-call-argument {#function-call-argument}
> #### function-call-argument {#function-call-argument}
>
> *函数调用参数* → [表达式](#expression) | [标识符](02-Lexical-Structure.md#identifier) **:** [表达式](#expression)
>
> *函数调用参数* → [运算符](./02_Lexical_Structure.md#operator) | [标识符](./02-Lexical-Structure.md#identifier) **:** [运算符](./02-Lexical-Structure.md#operator)
>
>
>
#### trailing-closure {#trailing-closure}
> #### trailing-closure {#trailing-closure}
>
> *尾随闭包* → [闭包表达式](#closure-expression)
>
> #### labeled-trailing-closures {#labeled-trailing-closures}
>
> *标签尾随闭包集* → [标签尾随闭包](#labeled-trailing-closure) [标签尾随闭包集](#labeled-trailing-closures)<sub>可选</sub>
>
> #### labeled-trailing-closure {#labeled-trailing-closure}
> *标签尾随闭包* → [标识符](./02-Lexical-Structure.md#identifier) **:** [闭包表达式](#closure-expression)
### 构造器表达式 {#initializer-expression}
*构造器表达式*用于访问某个类型的构造器,形式如下: