Swift学习笔记 (四十三) 词法结构

关键字和标点符号

下⾯这些被保留的关键字不允许用作标识符,除非使用反引号转义,具体描述请参考《标识符》。除了 inout 、 var 以及 let 之外

的关键字可以用作某个函数声明或者函数调用当中的外部参数名,无需添加反引号转义。当一个成员与一个关键字具有相同的名

称时,不需要使用反引号来转义对该成员的引用,除非在引用该成员和使用该关键字之间存在歧义 - 例如, self , Type 和 

Protocol 在显式的成员表达式中具有特殊的含义,因此它们必须在该上下文中使用反引号进⾏转义。

用在声明中的关键字:

 associatedtype 、 class 、 deinit 、 enum 、 extension 、 fileprivate 、 func 、 import 、 init 、 inout 、 internal 、 let 、

open 、 operator 、 private 、 protocol 、 public 、 static、 struct 、 subscript 、 typealias 以及 var 。

用在语句中的关键字: 

break 、 case 、 continue 、 default 、 defer 、 do 、 else 、 fallthrough 、 for 、 guar d、if、in、repeat、return、switch、

where 以及 while。

用在表达式和类型中的关键字: 

as 、 Any 、 catch 、 false 、 is 、 nil 、 rethrows 、 super 、 self 、 Self 、 throw 、throws 、 true 以及 try 。

用在模式中的关键字: _ 。

以井字号( # )开头的关键字:

 #available 、 #colorLiteral 、 #column 、 #else 、 #elseif 、 #endif 、 #error 、 #file、 #fileLiteral 、 #function 、 #if 、 

#imageLiteral 、 #line 、 #selector 、 #sourceLocation以及 #warning 。

特定上下⽂中被保留的关键字:

associativity 、 convenience 、 dynamic 、 didSet 、 final 、 get 、 infix 、 indirect 、 lazy 、 left 、 mutating 、 none 、 

nonmutating 、 optional 、 override 、 postfix 、 precedence、 prefix 、 Protocol 、 required 、 right 、 set 、 Type 、 

unowned 、 weak 以及 willSet 。 这些关键字在特定上下文之外可以被用做标识符。

以下符号被当作保留符号,不能用于自定义运算符:

( 、 ) 、 { 、 } 、 [ 、 ] 、 . 、 , 、 : 、 ; 、 = 、 @ 、 # 、 & (作为前缀运算符)、 -> 、 ` 、 ? 、 ! (作为后缀运算符)。

 

字面量

字⾯量(literal) 用来表示源码中某种特定类型的值,⽐如一个数字或字符串。

下⾯是字面量的一些示例:

42                              // 整数字⾯量

3.14159                     // 浮点数字⾯量

"Hello, world!"          // 字符串字⾯量

true                           // 布尔值字面量

字⾯量本身并不包含类型信息。事实上,一个字⾯量会被解析为拥有无限的精度,然后 Swift 的类型推导会尝试去推导出这个字

⾯量的类型。⽐如,在 let x: Int8 = 42 这个声明中,Swift 使用了显式类型注解( : Int8 )来推导出 42 这个整数字⾯量的类型是 

Int8 。如果没有可用的类型信息, Swift 则会从标准库中定义的字⾯量类型中推导出一 个默认的类型。整数字⾯量的默认类型是 

Int ,浮点数字⾯量的默认类型是 Double ,字符串字⾯量的默认类型是 String ,布尔值字⾯量的默认类型是 Bool 。比如,在 

let str = "Hello, world" 这个声明中,字符串"Hello, world" 的默认推导类型就是 String 。

当为一个字⾯量值指定了类型注解的时候,这个标注的类型必须能通过这个字⾯量值实例化。也就是说,这个类型必须符合这些

Swift 标准库协议中的一个:整数字⾯量的 IntegerLiteralConvertible 协议、浮点数字⾯量的 FloatingPointLiteralConvertible 

协议、字符串字⾯量的 StringLiteralConvertible 协议以及布尔值字⾯量的 BooleanLiteralConvertible 协议。比如, Int8 符合 

IntegerLiteralConvertible 协议,因此它能在 let x: Int8 = 42 这个声明中作为整数字⾯量 42 的类型注解。

 

整数字面量

整数字⾯量(Integer Literals) 表示未指定精度整数的值。整数字⾯量默认用十进制表示,可以加前缀来指定其他的进制。二进制

字⾯量加 0b ,⼋进制字⾯量加 0o ,十六进制字⾯量加 0x 。

十进制字⾯量包含数字 0 ⾄ 9 。⼆进制字⾯量只包含 0 或 1 ,八进制字⾯量包含数字 0 至 7 ,十六进制字⾯量包含数字 0 至 9 

以及字母 A ⾄ F (⼤小写均可)。

负整数的字⾯量在整数字⾯量前加负号 - ,比如 -42 。

整型字⾯量可以使用下划线( _ )来增加数字的可读性,下划线会被系统忽略,因此不会影响字⾯量的值。同样地,也可以在数字

前加 0 ,这同样也会被系统所忽略,并不会影响字⾯量的值。 除⾮特别指定,整数字⾯量的默认推导类型为 Swift 标准库类型中

的 Int 。Swift 标准库还定义了其他不同长度以及是否带符号的整数类型。

 

浮点数字⾯量

浮点数字⾯量(Floating-point literals) 表示未指定精度浮点数的值。 浮点数字⾯量默认用十进制表示(无前缀),也可以用十六进制

表示(加前缀 0x )。

十进制浮点数字⾯量由十进制数字串后跟小数部分或指数部分(或两者皆有)组成。⼗进制小数部分由小数点( . )后跟十进制数字串

组成。指数部分由大写或小写字母 e 为前缀后跟十进制数字串组成,这串数字表示 e 之前的数量乘以 10 的几次方。例如: 1.25e2 

表示 1.25 x 10的2次方,也就是 125.0 ;同样, 1.25e-2 表示 1.25 x 10的负2次方,也就是0.0125 。

十六进制浮点数字⾯量由前缀 0x 后跟可选的十六进制小数部分以及十六进制指数部分组成。十六进制小数部分由小数点后跟⼗

六进制数字串组成。指数部分由大写或小写字母 p 为前缀后跟十进制数字串组成,这串数字表示 p 之前的数量乘以 2 的几次⽅

方。例如: 0xFp2 表示 15 x 2的2次方,也就是 60 ;同样, 0xFp-2 表示 15 x 2的负2次方,也就是 3.75 。

负数的浮点数字⾯量由负号( - )和浮点数字⾯量组成,例如 -42.5 。

浮点数字⾯量允许使用下划线( _ )来增强数字的可读性,下划线会被系统忽略,因此不会影响字⾯量的值。同样地,也可以在数

字前加 0 ,并不会影响字⾯量的值。

除⾮特别指定,浮点数字⾯量的默认推导类型为 Swift 标准库类型中的 Double ,表示 64 位浮点数。Swift 标准库也定义了 Float 

类型,表示 32 位浮点数。

 

字符串字面量

字符串字⾯量是被引号包括的一串字符组成。 单⾏字符串字⾯量被包在双引号中的一串字符组成,形式如下:

" 字符 "

字符串字⾯量中不能包含未转义的双引号( " )、未转义的反斜线( \ )、回⻋符、换⾏符。 多⾏字符串字⾯量被包在三个双引号中

的一串字符组成,形式如下:

""" 字符 """

与单⾏字符串字⾯量不同的是,多⾏字符串字⾯量可以包含不转义的双引号("),回⻋以及换行。它不能包含三个未转义的连续双

引号。

""" 之后的回车或者换⾏开始多⾏字符串字⾯量,不是字符串的一部分。 """ 之前回车或者换⾏结束字⾯量,也不是字符串的一部

分。要让多⾏字符串字⾯量的开始或结束带有换行,就在第一⾏或者最后⼀⾏写⼀个空行。

多⾏字符串字⾯量可以使⽤任何空格或制表符组合进⾏缩进;这些缩进不会包含在字符串中。 """ 的结束符号决定了缩进:字面量中

的任何⼀个⾮空⾏必须起始于多⾏字符串字⾯量结束符号的前面;空格和制表符不会被转换。你可以包在缩进后含额外的空格和制

表符;这些空格和制表符会在字符串中出现。

多⾏字符串字⾯量中的一⾏结束使⽤规范化的换⾏符号。尽管你的源代码混⽤了回车和换⾏符,字符串中所有的⾏结束都必须⼀

样.

在多⾏字符串字⾯量里, 在⾏末用反斜线( \ )可以省略字符串行间中断。 反斜线之间的空⽩和⾏间中断也可以省略。 你可以在你

的代码⾥⽤这种语法硬包裹多⾏字符串字⾯量,不需要改变产⽣的字符串的值。

可以在字符串字⾯量中使用的转义特殊符号如下:

空字符  \0

反斜线  \\

⽔水平制表符  \t

换⾏行行符  \n

回⻋车符  \r

双引号  \"

单引号  \'

Unicode 标量 \u{ n } ,n 为一到八位的十六进制数字

字符串字⾯量允许在反斜杠( \ )后的括号 () 中插入表达式的值。插入表达式可以包含字符串字⾯量,但不能包含未转义的反斜线

( \ )、回⻋符以及换⾏符。

例如,以下所有字符串字⾯量的值都是相同的:

"1 2 3"

"1 2 \("3")"

"1 2 \(3)"

"1 2 \(1 + 2)"

let x = 3; "1 2 \(x)"

可以使用一对或多对扩展分隔符(#)包裹字符串进⾏分隔,被分隔的字符串的形式如下所示:

#" characters "#

#"""

characters

"""#

特殊字符在被分隔符分隔的结果字符串中会展示为普通字符,⽽不是特殊字符。你可以使用扩展分隔符来创建一些具有特殊效果

的字符串。例如,⽣成字符串插值,启动或终⽌转义序列(字符串)。

以下所示,由字符串字⾯量和扩展分隔符所创建的字符串是等价的:

let string = #"\(x) \ " \u{2603}"#

let escaped = "\\(x) \\ \" \\u{2603}"

print(string)

// Prints "\(x) \ " \u{2603}"

print(string == escaped)

// Prints "true"

如果在一个字符串中使用多对扩展分隔符,请不要在分隔符之间使用空格。

print(###"Line 1\###nLine 2"###) // OK

print(# # #"Line 1\# # #nLine 2"# # #) // Error

使用扩展分隔符创建的多⾏字符串字⾯量与普通多⾏字符串字⾯量具有相同的缩进要求。 字符串字⾯量的默认推导类型为 String 。

用 + 操作符连接的字符型字⾯量是在编译时进⾏连接的。⽐如下面的 textA 和 textB 是完全一样的, textA没有任何运⾏时的连

接操作。

let textA = "Hello " + "world"

let textB = "Hello world"

 

运算符

Swift 标准库定义了许多可供使用的运算符,其中大部分在《基础运算符》和《高级运算符》中进⾏了阐述。这一小节将描述哪

些字符能用于⾃定义运算符。

自定义运算符可以由以下其中之一的 ASCII 字符

/、=、-、+、!、*、%、<、>、&、|、^、? 以及 ~,或者后⾯语法中规定的任一个 Unicode 字符(其中包含了数学运算符、零散符

号(Miscellaneous Symbols) 以及印刷符号(Dingbats)之类的 Unicode 块)开始。在第一个字符之后,允许使用组合型 Unicode 字

符。

您也可以以点号( . )开头来定义自定义运算符。这些运算符可以包含额外的点,例如 .+. 。如果某个运算符不是以点号开头的,那

么它就无法再包含另外的点号了。例如, +.+ 就会被看作为一个 + 运算符后⾯跟着一个 .+ 运算符。

虽然您可以用问号 ? 来自定义运算符,但是这个运算符不能只包含单独的一个问号。此外,虽然运算符可以包含一个惊叹号 ! ,

但是前缀运算符不能够以问号或者惊叹号开头。

注意

以下这些标记 =、->、//、/*、*/、.、<(前缀运算符)、&、?、?(中缀运算符)、>(后缀运算符)、 ! 、 ? 是被系统保留的。这些符号

不能被重载,也不能用于自定义运算符。

运算符两侧的空白被用来区分该运算符是否为前缀运算符、后缀运算符或二元运算符。规则总结如下:

如果运算符两侧都有空白或两侧都无空白,将被看作二元运算符。例如: a+++b 和 a +++ b 当中的 +++ 运算符会被看作二元运算

符。

如果运算符只有左侧空白,将被看作一元前缀运算符。例如 a +++b 中的 +++ 运算符会被看做是一元前缀运算符。

如果运算符只有右侧空白,将被看作一元后缀运算符。例如 a+++ b 中的 +++ 运算符会被看作是一元后缀运算符。

如果运算符左侧没有空白并紧跟 . ,将被看作一元后缀运算符。例如 a+++.b 中的 +++ 运算符会被视为一元后缀运算符(即上式被

视为 a+++ .b ⽽不是 a +++ .b )。

鉴于这些规则,运算符前的字符 (、[ 和 {,运算符后的字符 )、] 和 },以及字符 ,、; 和 : 都被视为空白。

以上规则需注意一点,如果预定义运算符 ! 或 ? 左侧没有空白,则不管右侧是否有空白都将被看作后缀运算符。如果将 ? 用作可

选链式调用运算符,左侧必须无空白。如果用于条件运算符 ? : ,必须两侧都有空白。

在某些特定的设计中 ,以 < 或 > 开头的运算符会被分离成两个或多个符号,剩余部分可能会以同样的方式被再次分离。因此,

在 Dictionary<String, Array<Int>> 中没有必要添加空白来消除闭合字符 > 的歧义。在这个例子中, 闭合字符 > 不会被视为单独

的符号,因⽽不会被错误解析为 >> 运算符。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值