• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

Swift5.3语言参考(四)表达式

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:山青咏芝(shanqingyongzhi)
➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

热烈欢迎,请直接点击!!!

进入博主App Store主页,下载使用各个作品!!!

注:博主将坚持每月上线一个新app!!!

在Swift中,有四种表达式:前缀表达式,二进制表达式,主表达式和后缀表达式。评估表达式会返回一个值,导致副作用,或两者兼而有之。

前缀和二进制表达式允许您将运算符应用于较小的表达式。主要表达式在概念上是最简单的表达式,它们提供了一种访问值的方法。Postfix表达式(如前缀和二进制表达式)允许您使用后缀(例如函数调用和成员访问)构建更复杂的表达式。每种表达方式将在下面的部分中详细介绍。

1 GRAMMAR OF AN EXPRESSION
2 
3 expression → try-operator opt prefix-expression binary-expressions opt
4 
5 expression-list → expression | expression , expression-list

前缀表达式

前缀表达式将可选前缀运算符与表达式组合在一起。前缀运算符采用一个参数,即后面的表达式。

有关这些运算符的行为的信息,请参阅基本运算符高级运算符

有关Swift标准库提供的运算符的信息,请参阅运算符声明

除了标准库操作符之外,您还可以&在作为函数调用表达式的输入输出参数传递的变量名称之前使用有关更多信息和查看示例,请参阅In-Out参数

1 GRAMMAR OF A PREFIX EXPRESSION
2 
3 prefix-expression → prefix-operator opt postfix-expression
4 
5 prefix-expression → in-out-expression
6 
7 in-out-expression → & identifier

try运算符

一个尝试表达由的try操作之后,可以抛出一个错误的表达。它具有以下形式:

try expression

一个可选的试表达由的try?操作之后,可以抛出一个错误的表达。它具有以下形式:

try? expression

如果表达不抛出一个错误,可选的试表达式的值是一个可选包含的价值表达否则,optional-try表达式的值为nil

一个强制尝试表达由的try!操作之后,可以抛出一个错误的表达。它具有以下形式:

try! expression

如果表达式抛出错误,则会产生运行时错误。

当在二元运算左手侧上的表达被标记trytry?或者try!,该运算符适用于整个二进制表达式。也就是说,您可以使用括号来明确运算符的应用程序范围。

1 sum = try someThrowingFunction() + anotherThrowingFunction()   // try applies to both function calls
2 sum = try (someThrowingFunction() + anotherThrowingFunction()) // try applies to both function calls
3 sum = (try someThrowingFunction()) + anotherThrowingFunction() // Error: try applies only to the first function call

try表达式不能出现在二进制运算符的右手侧,除非二进制运算符是赋值运算符或try表达被括号括起来。

欲了解更多信息,看看如何使用的例子trytry?try!,看到错误处理

1 GRAMMAR OF A TRY EXPRESSION
2 
3 try-operatortry | try ? | try !

二进制表达式

二进制表达式将中缀二元运算符与其左手和右手参数所使用的表达式组合在一起。它具有以下形式:

left-hand argument operator right-hand argument

有关这些运算符的行为的信息,请参阅基本运算符高级运算符

有关Swift标准库提供的运算符的信息,请参阅运算符声明

注意

在分析时,由二元运算符组成的表达式表示为平面列表。通过应用运算符优先级将此列表转换为树。例如,表达最初理解为五个项目的平面列表,,和此过程将其转换为树(2 +(3 * 5))。52+3*5

 1 GRAMMAR OF A BINARY EXPRESSION
 2 
 3 binary-expression → binary-operator prefix-expression
 4 
 5 binary-expression → assignment-operator try-operator opt prefix-expression
 6 
 7 binary-expression → conditional-operator try-operator opt prefix-expression
 8 
 9 binary-expression → type-casting-operator
10 
11 binary-expressions → binary-expression binary-expressions opt

 

赋值运算符

赋值运算符设置为特定表达的新值。它具有以下形式:

expression = value

所述的值表达被设置为通过评估所获得的值的值如果表达式是元组,则该必须是具有相同元素数的元组。(允许使用嵌套元组。)从值的每个部分表达式的相应部分执行赋值例如:

1 (a, _, (b, c)) = ("test", 9.45, (12, 3))
2 // a is "test", b is 12, c is 3, and 9.45 is ignored

赋值运算符不返回任何值。

1 GRAMMAR OF AN ASSIGNMENT OPERATOR
2 
3 assignment-operator → =

三元条件运算符

所述三元条件运算符评估为基于条件的值两个给定值中的一个。它具有以下形式:

condition ? expression used if true : expression used if false

如果条件求值为true,则条件运算符计算第一个表达式并返回其值。否则,它将计算第二个表达式并返回其值。未评估未使用的表达式。

有关使用三元条件运算符的示例,请参阅三元条件运算符

1 GRAMMAR OF A CONDITIONAL OPERATOR
2 
3 conditional-operator → ? expression :

类型铸造运算符

有四种类型铸造运算符:is运算符,as运算符,as?运算符和as!运算符。

它们具有以下形式:

1 expression is type
2 expression as type
3 expression as? type
4 expression as! type

is在运行时运算符检查是否表达可以转换为指定的类型true如果表达式可以强制转换为指定的类型,则返回否则,它返回false

as当在该铸造总是成功,如向上转型或桥接编译时已知运算符进行的铸造。Upcasting允许您将表达式用作其类型的超类型的实例,而无需使用中间变量。以下方法是等效的:

 1 func f(_ any: Any) { print("Function for Any") }
 2 func f(_ int: Int) { print("Function for Int") }
 3 let x = 10
 4 f(x)
 5 // Prints "Function for Int"
 6 
 7 let y: Any = x
 8 f(y)
 9 // Prints "Function for Any"
10 
11 f(x as Any)
12 // Prints "Function for Any"

桥接允许您使用Swift标准库类型的表达式,例如String其相应的Foundation类型,例如NSString无需创建新实例。有关桥接的更多信息,请参阅使用基础类型

as?运算符执行的有条件铸造表达式为指定的类型as?运算符返回指定的可选类型在运行时,如果转换成功,表达式的值将包装在一个可选的并返回; 否则,返回的值是nil如果保证转换为指定类型失败或保证成功,则会引发编译时错误。

as!运算符执行的强制投表达为指定的类型as!运算符返回指定的值类型,而不是一个可选类型。如果强制转换失败,则会引发运行时错误。行为与行为相同as! T(x as? T)!

有关类型转换的更多信息以及查看使用类型转换运算符的示例,请参阅类型转换

1 GRAMMAR OF A TYPE-CASTING OPERATOR
2 
3 type-casting-operatoris type
4 
5 type-casting-operatoras type
6 
7 type-casting-operatoras ? type
8 
9 type-casting-operatoras ! type

主要表达

主表达式是最基本的表达式。它们可以单独用作表达式,它们可以与其他标记组合以生成前缀表达式,二进制表达式和后缀表达式。

 1 GRAMMAR OF A PRIMARY EXPRESSION
 2 
 3 primary-expression → identifier generic-argument-clause opt
 4 
 5 primary-expression → literal-expression
 6 
 7 primary-expression → self-expression
 8 
 9 primary-expression → superclass-expression
10 
11 primary-expression → closure-expression
12 
13 primary-expression → parenthesized-expression
14 
15 primary-expression → tuple-expression
16 
17 primary-expression → implicit-member-expression
18 
19 primary-expression → wildcard-expression
20 
21 primary-expression → key-path-expression
22 
23 primary-expression → selector-expression
24 
25 primary-expression → key-path-string-expression

文字表达

文字表达由任一普通的文字(如字符串或数字),阵列或字典文字,游乐场文字,或下列特殊文字中的一个:

文字 类型
#file String 它出现的文件的名称。
#line Int 它出现的行号。
#column Int 它开始的列号。
#function String 它出现的声明的名称。
#dsohandle UnsafeRawPointer DSO(动态共享对象)处理在它出现的地方使用。

在函数内部,值#function是该函数的名称,在方法中它是该方法的名称,在属性getter或setter中它是该属性的名称,在特殊成员内部init或者subscript是它的名称关键字,在文件的顶层,它是当前模块的名称。

当用作函数或方法参数的默认值时,在调用站点计算默认值表达式时,将确定特殊文字的值。

1 func logFunctionName(string: String = #function) {
2     print(string)
3 }
4 func myFunction() {
5     logFunctionName() // Prints "myFunction()".
6 }

一个字面数组是值的有序集合。它具有以下形式:

[value 1, value 2, ...]

数组中的最后一个表达式后面可以跟一个可选的逗号。数组文字的值具有类型[T],其中T是表达式的类型。如果有多种类型的表达式,T则是它们最接近的常见超类型。空数组文字使用一对空方括号编写,可用于创建指定类型的空数组。

var emptyArray: [Double] = []

一个字典文字是键值对的无序集合。它具有以下形式:

[key 1: value 1, key 2: value 2, ...]

字典中的最后一个表达式后面跟一个可选的逗号。字典文字的值具有类型,其中是键表达式的类型,并且是其值表达式的类型。如果存在多个类型的表达式,并且是它们各自值的最接近的公共超类型。空字典文字在一对方括号(内写为冒号,以区别于空数组文字。您可以使用空字典文字来创建指定键和值类型的空字典文字。[Key: Value]KeyValueKeyValue[:]

var emptyDictionary: [String: Double] = [:]

游乐场字面所使用的Xcode创建颜色,文件或图像程序编辑器内的交互式表示。Xcode之外的纯文本中的游乐场文字使用特殊的文字语法表示。

有关在Xcode中使用playground文字的信息,请参阅在Xcode帮助中添加颜色,文件或图像文字

 1 GRAMMAR OF A LITERAL EXPRESSION
 2 
 3 literal-expression → literal
 4 
 5 literal-expression → array-literal | dictionary-literal | playground-literal
 6 
 7 literal-expression → #file | #line | #column | #function | #dsohandle
 8 
 9 array-literal → [ array-literal-items opt ]
10 
11 array-literal-items → array-literal-item ,opt | array-literal-item , array-literal-items
12 
13 array-literal-item → expression
14 
15 dictionary-literal → [ dictionary-literal-items ] | [ : ]
16 
17 dictionary-literal-items → dictionary-literal-item ,opt | dictionary-literal-item , dictionary-literal-items
18 
19 dictionary-literal-item → expression : expression
20 
21 playground-literal → #colorLiteral ( red : expression , green : expression , blue : expression , alpha : expression )
22 
23 playground-literal → #fileLiteral ( resourceName : expression )
24 
25 playground-literal → #imageLiteral ( resourceName : expression )

Self表达

self表达是显式引用在其发生的类型的当前类型或实例。它有以下形式:

1 self
2 self.member name
3 self[subscript index]
4 self(initializer arguments)
5 self.init(initializer arguments)

在初始化程序,下标或实例方法中,self引用它出现的类型的当前实例。在类型方法中,self指的是它出现的当前类型。

self表达被用来访问成员时,提供消歧当在范围相同名称的另一变量,诸如函数的参数来指定范围。例如:

1 class SomeClass {
2     var greeting: String
3     init(greeting: String) {
4         self.greeting = greeting
5     }
6 }

在值类型的变异方法中,您可以为该值类型分配新实例self例如:

1 struct Point {
2     var x = 0.0, y = 0.0
3     mutating func moveBy(x deltaX: Double, y deltaY: Double) {
4         self = Point(x: x + deltaX, y: y + deltaY)
5     }
6 }
1 GRAMMAR OF A SELF EXPRESSION
2 
3 self-expression → self | self-method-expression | self-subscript-expression | self-initializer-expression
4 
5 self-method-expression → self . identifier
6 
7 self-subscript-expression → self [ function-call-argument-list ]
8 
9 self-initializer-expression → self . init

超类表达

一个超表达可以用其超一类交互。它具有以下形式之一:

1 super.member name
2 super[subscript index]
3 super.init(initializer arguments)

第一种形式用于访问超类的成员。第二种形式用于访问超类的下标实现。第三种形式用于访问超类的初始化程序。

子类可以在其成员,下标和初始化器的实现中使用超类表达式来使用其超类中的实现。

1 GRAMMAR OF A SUPERCLASS EXPRESSION
2 
3 superclass-expression → superclass-method-expression | superclass-subscript-expression | superclass-initializer-expression
4 
5 superclass-method-expression → super . identifier
6 
7 superclass-subscript-expression → super [ function-call-argument-list ]
8 
9 superclass-initializer-expression → super . init

闭合表达式

闭合表达式创建一个闭合,也被称为拉姆达匿名函数在其他编程语言。与函数声明一样,闭包包含语句,它从其封闭范围捕获常量和变量。它具有以下形式:

1 { (parameters) -> return type in
2     statements
3 }

参数具有相同的形式,如一个函数声明的参数,如描述函数声明

有几种特殊形式可以更简洁地编写闭包:

  • 闭包可以省略其参数的类型,返回类型或两者。如果省略参数名称和两种类型,请in在语句之前省略关键字。如果无法推断省略的类型,则会引发编译时错误。
  • 闭包可以省略其参数的名称。它的参数,然后隐式命名$,然后他们的立场:$0$1$2,等等。
  • 仅包含单个表达式的闭包被理解为返回该表达式的值。在对周围表达式执行类型推断时,还会考虑此表达式的内容。

以下闭包表达式是等效的:

 1 myFunction { (x: Int, y: Int) -> Int in
 2     return x + y
 3 }
 4 
 5 myFunction { x, y in
 6     return x + y
 7 }
 8 
 9 myFunction { return $0 + $1 }
10 
11 myFunction { $0 + $1 }

有关将闭包作为参数传递给函数的信息,请参阅函数调用表达式

闭包表达式可以在不存储在变量或常量中的情况下使用,例如当您立即使用闭包作为函数调用的一部分时。传递给myFunction上面代码的闭包表达式就是这种直接使用的例子。因此,闭包表达式是转义还是非转义取决于表达式的周围上下文。如果立即调用闭包表达式或作为非脱节函数参数传递,则闭包表达式是非脱节表达式。否则,闭包表达式正在转义。

有关转义闭包的详细信息,请参阅转义闭包

捕获列表

默认情况下,闭包表达式通过对这些值的强引用从其周围范围捕获常量和变量。您可以使用捕获列表显式控制在闭包中捕获值的方式。

捕获列表在参数列表之前写为以方括号括起的表达式的逗号分隔列表。如果使用捕获列表,则还必须使用in关键字,即使省略参数名称,参数类型和返回类型也是如此。

创建闭包时,将初始化捕获列表中的条目。对于捕获列表中的每个条目,常量初始化为在周围范围内具有相同名称的常量或变量的值。例如,在下面的代码中,a包含在捕获列表中但b不包含,这给了它们不同的行为。

 1 var a = 0
 2 var b = 0
 3 let closure = { [a] in
 4     print(a, b)
 5 }
 6 
 7 a = 10
 8 b = 10
 9 closure()
10 // Prints "0 10"

命名有两个不同的东西a,周围范围中的变量和闭包范围中的常量,但只有一个变量名为ba在内侧范围被初始化的值a在当创建所述闭合外范围,但是它们的值不以任何特殊的方式连接。这意味着更改a外部作用域中的值不会影响a内部作用域中a的值,闭包内部的更改也不会影响a闭包外部的相比之下,在外部范围中只有一个名为b-the的变量b因此在闭包内部或外部的变化在两个地方都可见。

当捕获的变量的类型具有引用语义时,此区别不可见。例如,x下面的代码中有两个命名,外部作用域中的变量和内部作用域中的常量,但由于引用语义,它们都引用同一个对象。

 1 class SimpleClass {
 2     var value: Int = 0
 3 }
 4 var x = SimpleClass()
 5 var y = SimpleClass()
 6 let closure = { [x] in
 7     print(x.value, y.value)
 8 }
 9 
10 x.value = 10
11 y.value = 10
12 closure()
13 // Prints "10 10"

如果表达式的值的类型是类,则可以使用weak标记捕获列表中的表达式,以捕获unowned对表达式值的弱或无主引用。

1 myFunction { print(self.title) }                    // implicit strong capture
2 myFunction { [self] in print(self.title) }          // explicit strong capture
3 myFunction { [weak self] in print(self!.title) }    // weak capture
4 myFunction { [unowned self] in print(self.title) }  // unowned capture

您还可以将任意表达式绑定到捕获列表中的命名值。创建闭包时将计算表达式,并使用指定的强度捕获值。例如:

1 // Weak capture of "self.parent" as "parent"
2 myFunction { [weak parent = self.parent] in print(parent!.title) }

有关闭包表达式的更多信息和示例,请参阅闭包表达式有关捕获列表的更多信息和示例,请参阅为闭包解决强引用循环

 1 GRAMMAR OF A CLOSURE EXPRESSION
 2 
 3 closure-expression → { closure-signature opt statements opt }
 4 
 5 closure-signature → capture-list opt closure-parameter-clause throwsopt function-result opt in
 6 
 7 closure-signature → capture-list in
 8 
 9 closure-parameter-clause → ( ) | ( closure-parameter-list ) | identifier-list
10 
11 closure-parameter-list → closure-parameter | closure-parameter , closure-parameter-list
12 
13 closure-parameter → closure-parameter-name type-annotation opt
14 
15 closure-parameter → closure-parameter-name type-annotation ...
16 
17 closure-parameter-name → identifier
18 
19 capture-list → [ capture-list-items ]
20 
21 capture-list-items → capture-list-item | capture-list-item , capture-list-items
22 
23 capture-list-item → capture-specifier opt expression
24 
25 capture-specifier → weak | unowned | unowned(safe) | unowned(unsafe)

隐式构件表达式

隐式构件表达式是访问类型的成员,例如枚举的情况下或类型的方法,在一个上下文,其中类型推理可确定隐含的类型的缩写方式。它具有以下形式:

.member name

例如:

1 var x = MyEnumeration.someValue
2 x = .anotherValue
1 GRAMMAR OF A IMPLICIT MEMBER EXPRESSION
2 
3 implicit-member-expression → . identifier

括号表达式

括号的表达式括号括起的表达式组成。您可以使用括号通过显式分组表达式来指定操作的优先级。分组括号不会更改表达式的类型 - 例如,类型(1)简单Int

1 GRAMMAR OF A PARENTHESIZED EXPRESSION
2 
3 parenthesized-expression → ( expression )

元组表达

元组表达由逗号分隔用括号括的表达式列表的。每个表达式前面都有一个可选的标识符,用冒号(:分隔它具有以下形式:

(identifier 1: expression 1, identifier 2: expression 2, ...)

元组表达式可以包含零个表达式,也可以包含两个或多个表达式。括号内的单个表达式是带括号的表达式。

注意

空元组表达式和空元组类型都是用()Swift 编写的。因为Void是类型别名(),您可以使用它来编写空元组类型。但是,像所有类型别名一样,Void它总是一个类型 - 你不能用它来写一个空的元组表达式。

1 GRAMMAR OF A TUPLE EXPRESSION
2 
3 tuple-expression → ( ) | ( tuple-element , tuple-element-list )
4 
5 tuple-element-list → tuple-element | tuple-element , tuple-element-list
6 
7 tuple-element → expression | identifier : expression

通配符表达

通配符表达式用于显式地忽略的分配期间的值。例如,在以下分配中分配10 x,忽略20:

1 (x, _) = (10, 20)
2 // x is 10, and 20 is ignored
1 GRAMMAR OF A WILDCARD EXPRESSION
2 
3 wildcard-expression → _

关键路径表达

关键路径表达是指一种类型的属性或下标。您可以在动态编程任务中使用键路径表达式,例如键值观察。它们具有以下形式:

\type name.path

类型名称是一个具体类型,包括任何通用的参数,如名称String[Int]Set<Int>

路径由属性名称,下标,可选链接表达式和强制解包表达式组成。这些关键路径组件中的每一个可以根据需要以任何顺序重复多次。

在编译时,键路径表达式被KeyPath的实例替换

要使用密钥路径访问值,请将密钥路径传递给subscript(keyPath:)下标,该下标适用于所有类型。例如:

1 struct SomeStructure {
2     var someValue: Int
3 }
4 
5 let s = SomeStructure(someValue: 12)
6 let pathToProperty = \SomeStructure.someValue
7 
8 let value = s[keyPath: pathToProperty]
9 // value is 12

类型名称


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
关东升的《从零开始学Swift》3月9日已经上架发布时间:2022-07-13
下一篇:
Swift中String取下标及性能问题发布时间:2022-07-13
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap