30.4. 字面量

字面量(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 标准库协议中的一个:整数字面量的 ExpressibleByIntegerLiteral 协议、浮点数字面量的 ExpressibleByFloatLiteral 协议、字符串字面量的 ExpressibleByStringLiteral 协议、布尔值字面量的 ExpressibleByBooleanLiteral 协议、只包含单个 Unicode 标量字符串文本的 ExpressibleByUnicodeScalarLiteral 协议以及只包含单个扩展字形簇(grapheme cluster)字符串文字的 ExpressibleByExtendedGraphemeClusterLiteral 协议。比如,Int8 符合 ExpressibleByIntegerLiteral 协议,因此它能在 let x: Int8 = 42 这个声明中作为整数字面量 42 的类型注解。

字面量语法

字面量数值字面量 | 字符串字面量 | 布尔值字面量 | [nil 字面量](#nil 字面量)

数值字面量- 可选 整数字面量 | - 可选 浮点数字面量

布尔值字面量true | false

nil 字面量nil

整数字面量

整数字面量(Integer Literals) 表示未指定精度的整数值。整数字面量默认用十进制表示;可以加前缀来指定其他的进制。二进制字面量加 0b,八进制字面量加 0o,十六进制字面量加 0x

十进制字面量包含数字 09。二进制字面量包含 01,八进制字面量包含数字 07,十六进制字面量包含数字 09 以及字母 AF(大小写均可)。

负整数字面量的表示方式为在整数字面量前加负号 -,比如 -42

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

除非特别指定,整数字面量的默认推导类型为 Swift 标准库类型中的 Int。Swift 标准库还定义了其他不同长度以及是否带符号的整数类型,请参考 2.5. 整数

整数字面量语法

integer-literal

整数字面量* → 二进制字面量

整数字面量 → 八进制字面量

整数字面量* → 十进制字面量

整数字面量 → 十六进制字面量

binary-literal

二进制字面量0b 二进制数字 二进制字面量字符组可选

binary-digit

二进制数字 → 数值 0 或 1

二进制字面量字符 → 二进制数字 | _

binary-literal-characters

二进制字面量字符组 → 二进制字面量字符 二进制字面量字符组可选

octal-literal

八进制字面量0o 八进字数字 八进制字符组可选

octal-digit

八进字数字 → 数值 0 到 7

八进制字符 → 八进字数字 | _

octal-literal-characters

八进制字符组 → 八进制字符 八进制字符组可选

decimal-literal

十进制字面量 → 十进制数字 十进制字符组可选

decimal-digit

十进制数字 → 数值 0 到 9

decimal-literal-characters

十进制数字组 → 十进制数字 十进制数字组可选

十进制字符 → 十进制数字 | _

十进制字符组 → 十进制字符 十进制字符组可选

hexadecimal-literal

十六进制字面量0x 十六进制数字 十六进制字面量字符组可选

hexadecimal-digit

十六进制数字 → 数值 0 到 9, 字母 a 到 f, 或 A 到 F

十六进制字符 → 十六进制数字 | -

hexadecimal-literal-characters

十六进制字面量字符组 → 十六进制字符 十六进制字面量字符组可选

浮点数字面量

浮点数字面量(Floating-point literals) 表示未指定精度浮点数的值。

浮点数字面量默认用十进制表示(无前缀),也可以用十六进制表示(加前缀 0x)。

十进制浮点数字面量由十进制数字串后跟十进制小数部分或十进制指数部分(或两者皆有)组成。十进制小数部分由小数点(.)后跟十进制数字串组成。指数部分由大写或小写字母 e 为前缀后跟十进制数字串组成,这串数字表示 e 之前的数值乘以 10 的几次方。例如:1.25e2 表示 1.25 x 10²,也就是 125.0。同样,1.25e-2 表示 1.25 x 10¯²,也就是 0.0125

十六进制浮点数字面量由前缀 0x 后跟可选的十六进制小数部分以及十六进制指数部分组成。十六进制小数部分由小数点后跟十六进制数字串组成。指数部分由大写或小写字母 p 为前缀后跟十进制数字串组成,这串数字表示 p 之前的数量乘以 2 的几次方。例如:0xFp2 表示 15 x 2²,也就是 60。同样,0xFp-2 表示 15 x 2¯²,也就是 3.75

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

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

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

浮点数字面量语法

floating-point-literal

浮点数字面量 → 十进制字面量 十进制分数可选 十进制指数可选

浮点数字面量 → 十六进制字面量 十六进制分数可选 十六进制指数

decimal-fraction

十进制分数. 十进制字面量

decimal-exponent

十进制指数 → 十进制指数 e 正负号可选 十进制字面量

hexadecimal-fraction

十六进制分数. 十六进制数字 十六进制字面量字符组可选

hexadecimal-exponent

十六进制指数 → 十六进制指数 p 正负号可选 十进制字面量

floating-point-e

十进制指数 ee | E

floating-point-p

十六进制指数 pp | P

sign

正负号+ | -

字符串字面量

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

字符串字面量中不能包含未转义的双引号(")、未转义的反斜线(\)、回车符、换行符。

多行字符串字面量被包在三个双引号中的一串字符组成,形式如下:""" 字符 """

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

""" 之后的回车或者换行开始多行字符串字面量,它们不是字符串的一部分。结束部分的 """ 以及它之前的回车或者换行,也不是字符串的一部分。要让多行字符串字面量的开始或结束带有换行,就在第一行或者最后一行写一个空行。

多行字符串字面量可以使用任何空格或制表符组合进行缩进;这些缩进不会包含在字符串中。""" 的结束符号决定了缩进:字面量中的每一个非空行开头都必须与结束符 """ 之前出现的缩进完全一致;空格和制表符不会被转换。你可以在缩进后包含额外的空格和制表符;这些空格和制表符会在字符串中出现。

多行字符串字面量中的一行结束使用规范化的换行符号。尽管你的源代码混用了回车和换行符,字符串中所有的行结束都必须一样.

在多行字符串字面量里,在行末用反斜线(\)可以省略字符串行间中断。反斜线和换行符之间的空白也将被忽略。你可以在你的代码里用这种语法硬包裹多行字符串字面量,而不改变结果字符串的值。

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

  • 空字符 (\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。更多有关 String 类型的信息请参考 第四章:字符串和字符

操作符连接的字符型字面量是在编译时进行连接的。比如下面的 textAtextB 是完全一样的,textA 没有任何运行时的连接操作。

let textA = "Hello " + "world"
let textB = "Hello world"

字符串字面量语法

字符串字面量 → 静态字符串字面量 | 插值字符串字面量

字符串开分隔定界符 → 字符串扩展分隔符 "

字符串闭分隔定界符" 字符串扩展分隔符可选

static-string-literal

静态字符串字面量 → 字符串开分隔定界符 引用文本可选 字符串闭分隔定界符

静态字符串字面量 → 多行字符串开分隔定界符 多行引用文本可选 多行字符串闭分隔定界符

多行字符串开分隔定界符 → 字符串扩展分隔符 """

多行字符串闭分隔定界符""" 字符串扩展分隔符

extended-string-literal-delimiter

字符串扩展分隔符# 字符串扩展分隔符可选

quoted-text

引用文本 → 引用文本项 引用文本可选

quoted-text-item

引用文本项 → 转义字符

引用文本项 → 除了 " 、**** 、U+000A、U+000D 以外的所有 Unicode 字符

multiline-quoted-text

多行引用文本 → 多行引用文本项 多行引用文本可选

multiline-quoted-text-item

多行引用文本项 转义字符可选

multiline-quoted-text

多行引用文本 → 除了 ** 以外的任何 Unicode 标量值

多行引用文本 → 转义换行

interpolated-string-literal

插值字符串字面量 → 字符串开分隔定界符 插值文本可选 字符串闭分隔定界符

插值字符串字面量 → 多行字符串开分隔定界符 插值文本可选 多行字符串闭分隔定界符

interpolated-text

插值文本 → 插值文本项 插值文本可选

interpolated-text-item

插值文本项( 表达式 ) | 引用文本项

多行插值文本 → 多行插值文本项 多行插值文本可选

多行插值文本项( 表达式 ) | 多行引用文本项

escape-sequence

转义序列 → ** 字符串扩展分隔符

escaped-character

转义字符 → 转义序列 0 | 转义序列 ** | 转义序列 t | 转义序列 n | 转义序列 r | 转义序列 " | 转义序列 '

转义字符 → 转义序列 u { unicode 标量数字 }

unicode-scalar-digits

unicode 标量数字 → 一到八位的十六进制数字

escaped-newline

转义换行符 → 转义序列 空白可选 断行符