Шаблоны
Сопоставление и распаковка значений.
Шаблон представляет структуру отдельного значения или составного значения. Например, структура кортежа (1, 2) — это список из двух элементов, разделённых запятыми. Поскольку шаблоны представляют структуру значения, а не конкретное значение, вы можете сопоставлять их с различными значениями. Например, шаблон (x, y) соответствует кортежу (1, 2) и любому другому кортежу из двух элементов. Помимо сопоставления шаблона со значением, вы можете извлечь часть или всё составное значение и привязать каждую часть к имени константы или переменной.
В Swift есть два основных типа шаблонов: шаблоны, которые успешно сопоставляются с любым типом значения, и шаблоны, которые могут не сопоставиться с заданным значением во время выполнения.
Шаблоны первого типа используются для распаковки значений в простых привязках переменных, констант и необязательных значений. К ним относятся шаблоны «подстановочного знака», шаблоны идентификаторов и любые шаблоны привязки значений или кортежей, содержащие их. Для этих шаблонов вы можете указать аннотацию типа, чтобы ограничить их сопоставление только значениями определённого типа.
Шаблоны второго типа используются для полного сопоставления шаблонов, когда значения, с которыми вы пытаетесь сопоставить, могут отсутствовать во время выполнения. К ним относятся шаблоны случаев перечисления, шаблоны необязательных значений, шаблоны выражений и шаблоны приведения типов. Эти шаблоны используются в метках случая оператора switch, в блоке catch оператора do или в условии случая оператора if, while, guard или for-in.
Грамматика шаблона:
шаблон → шаблон-подстановочного-знака аннотация-типа_?_
шаблон → шаблон-идентификатора аннотация-типа_?_
шаблон → шаблон-привязки-значения
шаблон → шаблон-кортежа аннотация-типа_?_
шаблон → шаблон-случая-перечисления
шаблон → шаблон-необязательного-значения
шаблон → шаблон-приведения-типов
шаблон → шаблон-выражения
Шаблон «подстановочного знака»
Шаблон «подстановочного знака» сопоставляет и игнорирует любое значение и состоит из нижнего подчеркивания (_). Используйте шаблон «подстановочного знака», когда вам не важны сопоставляемые значения. Например, следующий код итерирует по замкнутому диапазону 1...3, игнорируя текущее значение диапазона в каждом итерационном цикле:
for _ in 1...3 {
// Do something three times.
} Грамматика шаблона «подстановочного знака»:
шаблон-подстановочного-знака →
_
Шаблон идентификатора
Шаблон идентификатора сопоставляет любое значение и связывает сопоставленное значение с именем переменной или константы. Например, в следующем объявлении константы someValue — это шаблон идентификатора, который сопоставляет значение 42 типа Int:
let someValue = 42
При успешном сопоставлении значение 42 связывается (присваивается) с именем константы someValue.
Когда шаблон в левой части объявления переменной или константы является шаблоном идентификатора, шаблон идентификатора неявно является подшаблоном шаблона привязки значения.
Грамматика шаблона идентификатора:
шаблон-идентификатора → идентификатор
Шаблон привязки значения
Шаблон привязки значения связывает сопоставленные значения с именами переменных или констант. Шаблоны привязки значения, которые связывают сопоставленное значение с именем константы, начинаются с ключевого слова let; шаблоны, которые связывают с именем переменной, начинаются с ключевого слова var.
Идентификаторы внутри шаблона привязки значения связывают новые именованные переменные или константы со своими сопоставленными значениями. Например, вы можете разложить элементы кортежа и привязать значение каждого элемента к соответствующему шаблону идентификатора.
let point = (3, 2)
switch point {
// Bind x and y to the elements of point.
case let (x, y):
print("The point is at (\(x), \(y)).")
}
// Prints "The point is at (3, 2)." В приведённом примере let распространяется на каждый шаблон идентификатора в шаблоне кортежа (x, y). Из-за этого поведения случаи switch case let (x, y): и case (let x, let y): сопоставляют одни и те же значения.
Грамматика шаблона привязки значения:
шаблон-привязки-значения →
varшаблон |letшаблон
Шаблон кортежа
Шаблон кортежа — это список из нуля или более шаблонов, разделённых запятыми и заключённых в круглые скобки. Шаблоны кортежей сопоставляют значения соответствующих типов кортежей.
Вы можете ограничить шаблон кортежа, чтобы он соответствовал определённым видам типов кортежей, используя аннотации типов. Например, шаблон кортежа (x, y): (Int, Int) в объявлении константы let (x, y): (Int, Int) = (1, 2) сопоставляется только с типами кортежей, в которых оба элемента имеют тип Int.
Когда шаблон кортежа используется в качестве шаблона в операторе for-in или в объявлении переменной или константы, он может содержать только шаблоны «подстановочного знака», шаблоны идентификаторов, шаблоны необязательных значений или другие шаблоны кортежей, которые содержат эти шаблоны. Например, следующий код недействителен, поскольку элемент 0 в шаблоне кортежа (x, 0) — это шаблон выражения:
let points = [(0, 0), (1, 0), (1, 1), (2, 0), (2, 1)]
// This code isn't valid.
for (x, 0) in points {
/* ... */
} Круглые скобки вокруг шаблона кортежа, содержащего один элемент, не влияют на результат. Шаблон сопоставляется со значениями типа этого единственного элемента. Например, следующие шаблоны эквивалентны:
let a = 2 // a: Int = 2 let (a) = 2 // a: Int = 2 let (a): Int = 2 // a: Int = 2
Грамматика шаблона кортежа:
шаблон-кортежа →
(список-элементов-шаблона-кортежа_?_)
список-элементов-шаблона-кортежа → элемент-шаблона-кортежа | элемент-шаблона-кортежа,список-элементов-шаблона-кортежа
элемент-шаблона-кортежа → шаблон | идентификатор:шаблон
Шаблон случая перечисления
Шаблон случая перечисления сопоставляет случай существующего типа перечисления. Шаблоны случаев перечисления появляются в метках случая оператора switch и в условиях случая операторов if, while, guard и for-in.
Если случай перечисления, с которым вы пытаетесь сопоставить, имеет какие-либо связанные значения, соответствующий шаблон случая перечисления должен указать шаблон кортежа, содержащий по одному элементу для каждого связанного значения. Пример использования оператора switch для сопоставления случаев перечисления, содержащих связанные значения, см. <doc:Перечисления#Связанные-значения>.
Шаблон случая перечисления также сопоставляет значения этого случая, заключённые в необязательное значение. Эта упрощённая синтаксическая конструкция позволяет опустить шаблон необязательного значения. Обратите внимание, что поскольку Optional реализован как перечисление, .none и .some могут появиться в одном операторе switch, как и случаи типа перечисления.
enum SomeEnum { case left, right }
let x: SomeEnum? = .left
switch x {
case .left:
print("Turn left")
case .right:
print("Turn right")
case nil:
print("Keep going straight")
}
// Prints "Turn left" Грамматика шаблона случая перечисления:
шаблон-случая-перечисления → идентификатор-типа_?_
.имя-случая-перечисления шаблон-кортежа_?_
Шаблон необязательного значения
Шаблон необязательного значения сопоставляет значения, заключённые в случай some(Wrapped) перечисления Optional<Wrapped>. Шаблоны необязательных значений состоят из шаблона идентификатора, за которым сразу следует знак вопроса, и появляются в тех же местах, что и шаблоны случаев перечисления.
Поскольку шаблоны необязательных значений являются синтаксическим сахаром для шаблонов случаев перечисления Optional, следующие шаблоны эквивалентны:
let someOptional: Int? = 42
// Match using an enumeration case pattern.
if case .some(let x) = someOptional {
print(x)
}
// Match using an optional pattern.
if case let x? = someOptional {
print(x)
} Шаблон необязательного значения предоставляет удобный способ итерации по массиву необязательных значений в операторе for-in, выполняя тело цикла только для элементов, не являющихся nil.
let arrayOfOptionalInts: [Int?] = [nil, 2, 3, nil, 5]
// Match only non-nil values.
for case let number? in arrayOfOptionalInts {
print("Found a \(number)")
}
// Found a 2
// Found a 3
// Found a 5 Грамматика шаблона необязательного значения:
шаблон-необязательного-значения → шаблон-идентификатора
?
Шаблоны приведения типов
Существует два шаблона приведения типов: шаблон is и шаблон as. Шаблон is появляется только в метках случая оператора switch. Шаблоны is и as имеют следующий вид:
is <#type#> <#pattern#> as <#type#>
Шаблон is сопоставляет значение, если тип этого значения во время выполнения совпадает с типом, указанным в правой части шаблона is, или является подклассом этого типа. Шаблон is ведёт себя как оператор is, так как оба выполняют приведение типа, но отбрасывают возвращаемый тип.
Шаблон as сопоставляет значение, если тип этого значения во время выполнения совпадает с типом, указанным в правой части шаблона as, или является подклассом этого типа. При успешном сопоставлении тип сопоставленного значения приводится к типу, указанному в правой части шаблона as.
Пример использования оператора switch для сопоставления значений с шаблонами is и as см. в <doc:TypeCasting#Type-Casting-for-Any-and-AnyObject>.
Грамматика шаблона приведения типов:
шаблон-приведения-типов → шаблон-is | шаблон-as
шаблон-is →isтип
шаблон-as → шаблонasтип
Шаблон выражения
Шаблон выражения представляет значение выражения. Шаблоны выражений появляются только в метках случая оператора switch.
Выражение, представленное шаблоном выражения, сравнивается со значением входного выражения с помощью оператора сопоставления шаблонов (~=) из стандартной библиотеки Swift. Сопоставление успешно, если оператор ~= возвращает true. По умолчанию оператор ~= сравнивает два значения одного типа с помощью оператора ==. Он также может сопоставлять значение с диапазоном значений, проверяя, находится ли значение в этом диапазоне, как показано в следующем примере.
let point = (1, 2)
switch point {
case (0, 0):
print("(0, 0) is at the origin.")
case (-2...2, -2...2):
print("(\(point.0), \(point.1)) is near the origin.")
default:
print("The point is at (\(point.0), \(point.1)).")
}
// Prints "(1, 2) is near the origin." Вы можете перегрузить оператор ~=, чтобы задать пользовательское поведение сопоставления выражений. Например, вы можете переписать предыдущий пример, чтобы сравнить выражение point со строковыми представлениями точек.
// Overload the ~= operator to match a string with an integer.
func ~= (pattern: String, value: Int) -> Bool {
return pattern == "\(value)"
}
switch point {
case ("0", "0"):
print("(0, 0) is at the origin.")
default:
print("The point is at (\(point.0), \(point.1)).")
}
// Prints "The point is at (1, 2)." Грамматика шаблона выражения:
шаблон-выражения → выражение
This source file is part of the Swift.org open source project
Copyright © 2014 - 2025 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception