Видеокурсы по изучению языка программирования Swift. Подробнее

Выражения

Если вы нашли опечатку в тексте, выделите ее и нажмите CTRL + ENTER.

В Swift существуют четыре вида выражений: префиксные, бинарные, первичные и постфиксные выражения. При оценке выражения происходит возврат значения, вызывается побочный эффект, или и то и другое.

Префиксные и бинарные выражения позволяют применять операторы к небольшим выражениям. Первичные выражения концептуально являются самым простым видом выражений и обеспечивают способ доступа к значениям. Постфиксные выражения, также как префиксные и бинарные выражения, позволяют создавать более сложные выражения с использованием постфиксов: такие как вызов функций и доступ к членам. Каждый вид выражений подробно описан в разделах ниже.

Грамматика выражений

expression → try-operator ­opt­ prefix-expression ­binary-expressions­opt­
expression-list → expression­  | expression­expression-list­

Префиксные выражения

Префиксные выражения объединяют префиксный оператор опционального префикса и выражение. Префиксные операторы принимают один аргумент - выражение, следующее за ними.

Подробнее об этих операторах см. Базовые операторы и Продвинутые операторы.

Получить информацию об операторах, предоставляемых стандартной библиотекой Swift, см. Swift Standard Library Operators Reference.

В дополнение к стандартным библиотечным операторам, можно использовать & непосредственно перед именем переменной, которая передается как in-out аргумент выражению вызова функции. Для получения дополнительной информации см. Сквозные параметры.

Грамматика префиксных выражений

prefix-expression prefix-operator­opt ­postfix-expression­
prefix-expression in-out-expression­
in-out-expression &­ identifier­

Оператор Try

Выражение Try состоит из оператора try, за которым следует выражение, которое может генерировать ошибку. Выглядит вот так:

try выражение

Опциальное выражение try состоит из оператора try?, за которым следует выражение, которое может генерировать ошибку. Выглядит вот так:

try? выражение

Если выражение не генерируеи ошибку, значение опционального выражения try - это опционал, содержащий значение выражения. Другими словами значение опционального выражения try будет равно nil.

Выражение forced-try состоит из оператора try!, за которым следует выражение, которое может генерировать ошибку. Выглядит вот так:

try! выражение

Если выражение генерирует ошибку, выходит ошибка выполнения.

Когда выражение слева бинарного оператора отмечено try, try?, или try!, оператор применяется ко всему бинарному выражению. Тем не менее, вы можете использовать круглые скобки, чтобы явно указать сферу применения оператора.

sum = try someThrowingFunction() + anotherThrowingFunction()   // try применяется к обоим вызовам функций
sum = try (someThrowingFunction() + anotherThrowingFunction()) // try применяется к обоим вызовам функций
sum = (try someThrowingFunction()) + anotherThrowingFunction() // Error: try применяется только к первой функции

Выражение try не может появится справа бинарного оператора до той поры, пока бинарный оператор не является оператором присваивания или выражение try не заключено в скобки.

Подробнее о try, try?, и try! см. Обработка ошибок.

Грамматика выражения try

try-operator try­ | try­?­ | try­!­

Бинарные выражения

Бинарные выражения объединяют инфиксный бинарный оператор и выражение, которое принимает левосторонние и правосторонние аргументы. Вот так оно выглядит: 

аргумент слева оператор аргумент справа

Подробнее см. Базовые операторы и Продвинутые операторы.

Подробнее о операторах, представленных в стандартной библиотеке Swift читайте в Swift Standard Library Operators Reference.

Заметка

Во время парсинга, выражение из бинарных операторов выглядит как простой список. Этот список превращается в дерево через порядок выполнения операций. Например, выражение 2 + 3 * 5 изначально понимается как список из пяти пунктов, 2, +, 3, *, и 5. Этот процесс преобразует его в дерево (2 + (3 * 5)).

Грамматика бинарных выражений

binary-expression → binary-operator­ prefix-expression­
binary-expression → assignment-operator ­try-operator­opt ­prefix-expression­
binary-expression → conditional-operator­ try-operator­opt ­prefix-expression­
binary-expression → type-casting-operator­
binary-expressions → binary-expression ­binary-expressions­opt­

Оператор присваивания

Оператор присваивания устанавливает новое значение для данного выражения. Выглядит он вот так:

выражение = значение

Значение выражения устанавливается равным значению, полученному путем оценки значения. Если выражение является кортежем, то значение должно быть кортежем с таким же количеством элементов. (Вложенные кортежи допускаются.) Присваивание осуществляется из каждой части значения к соответствующей части выражения. Например:

(a, _, (b, c)) = ("test", 9.45, (12, 3))
// a равен "test", b равно 12, c равно 3, а 9.45 игнорируется

Оператор присваивания не возвращает никакого значения.

Грамматика оператора присваивания

assignment-operator

Тернарный условный оператор

Тернарный условный оператор принимает значение одного из двух заданных значений в зависимости от условия. Выглядит это так:

условие ? выражение при true : выражение при false

Если условие true, условный оператор вычисляет первое выражение и возвращает его значение. В противном случае, он вычисляет второе выражение и возвращает его значение. Неиспользованное выражение не вычисляется.

Подробнее см. Тернарный условный оператор.

Грамматика условного оператора

conditional-operator → ?­ try-operator­opt­  expression­

Операторы приведения типа

Существует четыре типа операторов приведения типа: оператор is, оператор as, оператор as?, и оператор as!.

Выглядят они вот так:

выражение is тип
выражение as тип
выражение as? тип
выражение as! тип

Оператор is во время выполнения задачи проверяет может ли выражение быть приведено к указанному типу. Возврат true происходит, если выражение может быть приведено к указанному типу, в противном случае, будет возвращено false.

Оператор as выполняет приведение, когда во время компиляции становится известно, что приведение пройдет успешно, например приведение к базовому типу или bridging. Приведение к базовому типу позволяет использовать выражение как экземпляр супертипа своего типа, без использования промежуточной переменной. Следующие подходы эквивалентны:

func f(_ any: Any) { print("Функция для Any") }
func f(_ int: Int) { print("Функция для Int") }
let x = 10
f(x)
// Выведет "Функция для Int"
 
let y: Any = x
f(y)
// Выведет "Функция для Any"
 
f(x as Any)
// Выведет "Функция для Any”

Bridging позволяет использовать выражение типа стандартной библиотеки Swift, такое как String, в качестве соответствующего типа Foundation, такое как NSString, без необходимости создания нового экземпляра. Для получения дополнительной информации см. Working with Cocoa Data Types in Using Swift with Cocoa and Objective-C (Swift 3).

Оператор as? выполняет условное приведение выражения к указанному типу. Оператор as? возвращает опционал указанного типа. Во время выполнения, если приведение завершается успешно, то значение выражения заворачивают в опционал и возвращают, в противном случае, возвращаемое значение равно nil. Если приведение к указанному типу гарантированно провалится или гарантированно пройдет успешно, то возникнет ошибка во время компиляции.

Оператор as! выполняет принудительное приведение выражения к указанному типу. Оператор as! возвращает значение указанного типа, а не опционального. Если приведение терпит неудачу, возникает ошибка выполнения. Поведение x as! T такое же, как поведение (x as? T)!.

Подробнее см. Приведение типов.

Грамматика операторов приведения типа

type-casting-operator → is­ type­
type-casting-operator → as ­type­
type-casting-operator → as­ ? ­type­
type-casting-operator → as­ !­ type­

Первичные выражения

Первичные выражения являются самым основным видом выражений. Они могут быть использованы в качестве самостоятельных выражений, могут быть объединены с другими токенами для создания префиксных выражений, бинарных выражений, и постфиксных выражений.

Грамматика первичных выражений

primary-expression → identifier­ generic-argument-clause­ opt­
primary-expression → literal-expression­
primary-expression → self-expression­
primary-expression → superclass-expression­
primary-expression → closure-expression­
primary-expression → parenthesized-expression­
primary-expression → implicit-member-expression­
primary-expression → wildcard-expression­
primary-expression → selector-expression­

Выражения литерала

Литеральное выражение состоит либо из обычного литерала (например, строки или числа), или литерала массива или словаря, или одного из следующих специальных литералов:

Литерал Тип Значение
#file String Имя файла, в котором он появляется.
#line Int Номер строки, в которой он появляется.
#column Int Номер столбца, с которого он начинается.
#function String Имя объявления, в которой он появляется.

Внутри функции значение #function - это имя этой функции, внутри метода - это имя этого метода, внутри свойства геттера или сеттера - это имя этого свойства, внутри специальных элементов, таких как init или subscript - это имя ключевого слова, а на верхнем уровне файла - это имя текущего модуля.

При использовании в качестве дефолтного значения функции или метода, значение специального литерала определяется, когда значение дефолтного выражения вычисляется на месте вызова.

func logFunctionName(string: String = #function) {
    print(string)
}
func myFunction() {
   logFunctionName() // Выведет "myFunction()".
}

Литерал массива представляет собой упорядоченную совокупность значений. Он выглядит следующим образом:

[значение 1, значение 2, ...]

Последнее выражение в массиве может сопровождаться дополнительной запятой. Значение литерала массива имеет тип [T], где T - это тип выражения внутри него. Если есть выражения нескольких типов, то T их ближайший общий родительский тип. Пустые литералы массива записываются с использованием пустой пары квадратных скобок и могут быть использованы для создания пустого массива заданного типа.

var emptyArray: [Double] = []

Литерал словаря представляет собой неупорядоченный набор пар ключ-значение. Выглядит он так:

[ключ 1: значение 1, ключ 2: значение 2, ...]

Последнее выражение в словаре может сопровождаться дополнительной запятой. Значение литерала словаря имеет тип [Key: Value] ([Ключ: Значение]), где Key - это тип его ключевых выражений и Value - это тип его выражений значений. Если есть выражения нескольких типов, то Key и Value являются ближайшим супертипом для их соответствующих значений. Пустой литерал словаря пишется как двоеточие внутри пары скобок ([:]), чтобы можно было отличить его от пустого литерала массива. Вы можете использовать пустой литерал словаря для создания пустого литерала словаря установленных ключей и значений типов.

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

Грамматика выражения литерала

literal-expression → literal­
literal-expression → array-literal­  | dictionary-literal |­  playground-literal­
literal-expression → #file­  | #line­ | #column­  |  #function­
array-literal → array-literal-items­opt­
array-literal-items → array-literal-item­opt­  array-literal-item­array-literal-items­
array-literal-item → expression­
dictionary-literal → dictionary-literal-items­ |
dictionary-literal-items → dictionary-literal-item­opt­ dictionary-literal-item­dictionary-literal-items­
dictionary-literal-item → expression­expression­
playground-literal → #colorLiteral­ (­ red­ ­expression­,­ green­ : ­expression­,­ blue­ ­expression­, ­alpha­ ­expression­
playground-literal → #fileLiteral­ (­ resourceName­ : ­expression­
playground-literal → #imageLiteral­ (­ resourceName­ : ­expression­

Выражение Self

Выражение self - это явная ссылка на текущий тип или экземпляр типа, в котором он находится. Выглядит следующим образом:

self
self.member name
self[subscript index]
self(initialiser arguments)
self.init(initialiser arguments)

В инициализаторе, сабскрипте, или методе экземпляра, self относится к текущему экземпляру типа, в котором находится. В типе метода self относится к текущему типу, в котором находится.

Выражение self используется для определения сферы охвата при доступе пользователей, обеспечивая устранения неоднозначности, когда есть другая переменная с тем же именем в области видимости, например в качестве параметра функции. Например:

class SomeClass {
    var greeting: String
    init(greeting: String) {
        self.greeting = greeting
    }
}

В mutating методе типа значения, вы можете назначить новый экземпляр этого типа значения на self. Например:

struct Point {
   var x = 0.0, y = 0.0
   mutating func moveBy(x deltaX: Double, y deltaY: Double) {
      self = Point(x: x + deltaX, y: y + deltaY)
   }
}

Грамматика выражения self

self-expression → self­  self-method-expression­  | self-subscript-expression­ | self-initializer-expression­
self-method-expression → self­identifier­
self-subscript-expression → self­expression-list­
self-initializer-expression → self­init­

Выражение суперкласса

Выражение суперкласса позволяет классу взаимодействовать с его суперклассом. И имеет одну из следующих форм:

super.имя члена
super[индекс сабскрипта]
super.init(аргументы инициализатора)

Первая форма используется для доступа к элементу суперкласса. Вторая форма используется для доступа к реализации суперкласса по индексу сабскрипта. Третья форма используется для доступа к инициализатору суперкласса.

Подклассы могут использовать выражение суперкласса в реализации членов, индексации и инициализаторах для того, чтобы с пользой использовать реализацию в их суперклассе.

Грамматика выражения суперкласса

superclass-expression → superclass-method-expression­  | superclass-subscript-expression­ | superclass-initializer-expression­
superclass-method-expression → super­identifier­
superclass-subscript-expression → super­expression-list­ superclass-initializer-expression → super­init­

Выражение замыкания

Выражение замыкания создает замыкание. В других языках программирования оно известно как лямбда или анонимная функция. Также как при объявлении функции, замыкание содержит заявления, которые выполняет, и вылавливает константы и переменные из области видимости. Имеет следующий вид:

{ (parameters) -> return type in
    statements
}

Параметры имеют ту же форму, что и параметры в объявлении функции, как описано в Функции.

Есть несколько специальных форм, которые позволяют замыканиям быть записанными более кратко:

  • Замыкание может опускать типы его параметров, тип возвращаемого значения, или все вместе. Если опустить имена параметров и оба типа, то необходимо опустить ключевое слово in перед заявлениями. Если опущенные типы не могут быть выведены, то возникает ошибка во время компиляции.
  • Замыкание может опускать имена своих параметров. Затем эти параметры неявно называются $, и за ними следуют: $0, $1, $2, и так далее.
  • Замыкание, которое состоит только из одного выражения, возвращает значение этого выражения. Содержание этого выражения также учитывается при выполнении вывода типа на окружающее выражение.

Следующие выражения замыкания эквивалентны:

myFunction {
    (x: Int, y: Int) -> Int in
    return x + y
}
 
myFunction {
    (x, y) in
    return x + y
}
 
myFunction { return $0 + $1 }
 
myFunction { $0 + $1 }

Для получения дополнительной информации о передаче замыкания в качестве аргумента функции, см. далее в Выражении вызова функции.

Списки захвата

По умолчанию выражение замыкания захватывает константы и переменные из окружающей его области с сильными ссылками на эти значения. Вы можете использовать списки захвата для того, чтобы явно контролировать то, какие значения захватываются замыканием.

Список захвата записывается в виде разделенного запятыми списка выражений в квадратных скобках, перед списком параметров. Если вы используете список захвата, вы должны также использовать ключевое слово in, даже если вы опускаете имена параметров, типы параметров и тип возвращаемого значения.

Записи в списке захвата инициализируются при создании замыкания. Для каждой записи в списке захвата, константа инициализируется со значением константы или переменной, которая имеет то же имя в окружающей области. Например, в коде ниже, a включено в список захвата, а b нет, и это приводит к их различному поведению.

var a = 0
var b = 0

let closure = { [a] in
    print(a, b)
}

a = 10
b = 10

closure()
// Выведет "0 10"

Здесь и переменная в окружающей области и константа в области замыкания имеют имя a, но есть только одна переменная с именем b. Когда создается замыкание, a во внутренней области инициализируется со значением a внешней области, но их значения как-то особенно не объединены. Это означает, что изменение величины a во внешней области не влияет на величину a во внутренней области, а также изменение a внутри замыкания не влияет на величину a вне замыкания. В отличие от этого, существует только одна переменная с именем b - это b во внешней области, так что изменения внутри и снаружи замыкания видны в обоих местах.

Этого различия не видно, когда тип захваченной переменной имеет ссылочную семантику. Например, в коде ниже переменная во внешней области и константа во внутренней области имеют имя x:, но они относятся к одному объекту из-за ссылочной семантики.

class SimpleClass {
    var value = 0
}

var x = SimpleClass()
var y = SimpleClass()

let closure = { [x] in
    print(x.value, y.value)
}

x.value = 10
y.value = 10

closure()
// Выведет "10 10"

Если тип значения выражения является классом, то вы можете отметить выражение в списке захвата как weak или unowned для захвата слабой или бесхозной ссылки на значение выражения.

myFunction { print(self.title) }                    // strong захват
myFunction { [weak self] in print(self!.title) }    // weak захват
myFunction { [unowned self] in print(self.title) }  // unowned захват

Кроме того, можно связать произвольное выражение с именованным значением в списке захвата. Выражение вычисляется, когда создается замыкание, а значение захватывается с заданной "силой". Например:

// Weak захват "self.parent" как "parent"
myFunction { [weak parent = self.parent] in print(parent!.title) }

Подробнее о выражениях замыкания см. Замыкания.  Подробнее о списках захвата см. Захват значений.

Грамматика выражений замыканий

closure-expression → {closure-signature opt­ statements}
‌closure-signature → capture-list opt­ closure-parameter-clause throws  opt­ function-result opt­ in
‌closure-signature → capture-list in
‌closure-parameter-clause → ( ) | (closure-parameter-list) | identifier-list
‌closure-parameter-list → closure-parameter | closure-parameter, closure-parameter-list
‌closure-parameter → closure-parameter-nametype-annotation opt­
‌closure-parameter → closure-parameter-nametype-annotation...
‌closure-parameter-name → identifier
‌capture-list → [capture-list-items]
‌capture-list-items → capture-list-item capture-list-item, capture-list-items
‌capture-list-item → capture-specifier opt­ expression
‌capture-specifier → weak  | unowned | unowned(safe) |  unowned(unsafe)

Неявное выражение члена

Неявное выражение члена представляет собой сокращенный способ доступа к члену типа, такому как кейс перечисления или тип метода, в контексте, когда определение типа может определить подразумеваемый тип. Выглядит это так:

.имя члена

Например:

var x = MyEnumeration.SomeValue
x = .AnotherValue

Грамматика неявного выражения члена

implicit-member-expression identifier­

Выражение в скобках

Выражения в скобках состоят из выражения, окруженного круглыми скобками. Вы можете использовать круглые скобки для явного указания приоритета выполнения той или иной операци. Группирвка при помощи скобок никак не меняет типа выражения. Например, тип выражения в скобках (1) является Int.

Грамматика выражения в скобках

parenthesized-expression → expression­)

Выражение кортежа

Выражение кортежа состоит из списка разделенных запятыми выражений, взятых в круглые скобки. Каждое выражение может иметь опциональный идентификатор перед ним, разделенный со своим значением через двоеточие (:). Выглядит оно вот так:

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

Выражение кортежа может иметь 0 выражений или может содержать два или более выражений. Если в скобках находится всего одно выражение, то это уже является выражением в скобках, а не кортежем.

Грамматика выражения кортежа

tuple-expression →  | tuple-element­tuple-element-list­
tuple-element-list → tuple-element­  | tuple-element­tuple-element-list­
tuple-element → expression­  | identifier­expression­

Выражение wildcard

Выражение с подстановочными символами используется для явного игнорирования значения во время присваивания. Например, при следующем присваивании 10 присваивается к x и 20 игнорируется:

(x, _) = (10, 20)
// x равно 10, а значение 20 игнорируется

Грамматика выражения wildcard

wildcard-expression

Выражение селектора

Выражение селектора позволяет получить доступ к селектору, используемому для обозначения метода или геттера или сеттора свойства в Objective-C.

#selector(имя метода)
#selector(getter: имя свойства)
#selector(setter: имя свойства)

Имя метода и имя свойства должны быть ссылкой на метод или свойство, который во время выполнения будут доступны в Objective-C. Значение выражения селектора является экземпляром типа Selector. Например:

class SomeClass: NSObject {
    let property: String
    @objc(doSomethingWithInt:)
    func doSomething(_ x: Int) { }
 
    init(property: String) {
        self.property = property
    }
}
let selectorForMethod = #selector(SomeClass.doSomething(_:))
let selectorForPropertyGetter = #selector(getter: SomeClass.property)

Когда создаем селектор для геттера свойства, имя свойства может быть ссылкой на переменную или константу свойства. И наоборот, когда создаем селектор для сеттера свойства, имя свойства должно быть ссылкой на переменное свойство.

Имя метода может содержать скобки для группировки, также как оператор as содержит их для устранения неоднозначности между методами, которые разделяют имя, но имеют разные типов сигнатур. Например:

extension SomeClass {
    @objc(doSomethingWithString:)
    func doSomething(_ x: String) { }
}
let anotherSelector = #selector(SomeClass.doSomething(_:) as (SomeClass) -> (String) -> Void)

Поскольку селектор создается во время компиляции, а не во время выполнения, компилятор может проверить существование  метода и то, что метод передается Objective-C.

Заметка

Не смотря на то, что имя метода и имя свойства являются выражением, они никогда не оценивается.

Грамматика выражения селектора

selector-expression → #selector ( expression )
‌selector-expression → #selector ( getter: expression )
‌selector-expression → #selector ( setter: expression )

Выражение знаячения пути по ключу

Выражения пути по ключу позволяют вам получить доступ к строке, которая относится к свойству в Objective-C для использования в KVC и в KVO API's.

#keyPath(имя свойства)

Имя свойства должно ссылаться на свойство, которое доступно во время исполнения в Objective-C. Во время компилляции выражение пути отображается в виде строкового литерала. Например:

@objc class SomeClass: NSObject {
   var someProperty: Int
   init(someProperty: Int) {
       self.someProperty = someProperty
   }
   func keyPathTest() -> String {
      return #keyPath(someProperty)
   }
}
 
let c = SomeClass(someProperty: 12)
let keyPath = #keyPath(SomeClass.someProperty)
print(c.value(forKey: keyPath))
// Выведет "Optional(12)"
 
print(keyPath == c.keyPathTest())
// Выведет "true"

Так как путь создается во время компилляции, а не во время исполнения, компилятор может проверить, что свойство существует и открыто для Objective-C исполнения.

Заметка

Несмотря на то, что имя свойства является выражением, оно никогда не оценивается.

Грамматика выражения зачения пути по ключу

key-path-expression → #keyPath ( expression )

Постфиксные выражения

Постфиксные выражения получаются путем применения постфиксного оператора или другого постфиксного синтаксиса к выражению. Синтаксически, каждое первичное выражение - это постфиксное выражение.

Для получения информации о поведении этих операторов см. Базовые операторы и Продвинутые операторы.

Для получения информации о предоставляемых стандартной библиотекой Swift операторах см. Swift Standard Library Operators Reference.

Грамматика постфиксных выражений

postfix-expression → primary-expression­
postfix-expression → postfix-expression­postfix-operator­
postfix-expression → function-call-expression­
postfix-expression → initializer-expression­
postfix-expression → explicit-member-expression­
postfix-expression → postfix-self-expression­
postfix-expression → dynamic-type-expression­
postfix-expression → subscript-expression­
postfix-expression → forced-value-expression­
postfix-expression → optional-chaining-expression­

Выражение вызова функции

Выражение вызова функции состоит из имени функции, за которой следует разделенный запятыми список аргументов функции в скобках. Вызов функции выражения имеют следующий вид:

имя функции(значение аргумента №1, значение аргумента №2)

Именем функции может быть любое выражение, значение которого имеет функциональный тип.

Если определение функции включает в себя имена параметров, то написание вызова функции должно первоначально включать в себя имена, а затем и значения аргументов, разделенных двоеточием (:). Выглядит это вот так:

имя функции(имя аргумента №1: значение аргумента №1,
имя аргумента №2: значение аргумента №2)

Выражение вызова функции может включать последующее замыкание в виде выражения замыкания сразу после закрывающей скобки. Последующее замыкание понимается как аргумент функции, добавленное после последнего аргумента в скобках. Следующие вызовы функций эквивалентны:

// someFunction принимает Int и замыкание в качестве своих аргументов
someFunction(x: x, f: {$0 == 13})
someFunction(x: x) {$0 == 13}

Если последующее замыкание является единственным аргументом функции, круглые скобки могут быть опущены.

// someFunction takes a closure as its only argument
myData.someMethod() {$0 == 13}
myData.someMethod {$0 == 13}

Грамматика выражения вызова функции

function-call-expression → postfix-expression ­parenthesized-expression­
function-call-expression → postfix-expression ­parenthesized-expression­opt­ trailing-closure­
trailing-closure → closure-expression­

Выражение инициализатора

Выражение инициализатора обеспечивает доступ к инициализатору типа. Имеет следующий вид:

выражение.init(аргументы инициализатора)

Вы используете выражение инициализатора в выражение вызова функции для инициализации нового экземпляра типа. Вы также использовуете выражение инициализатора для делегирования инициализатору суперкласса.

class SomeSubClass: SomeSuperClass {
    override init() {
        // инициализация подкласса
        super.init()
    }
}

Как и функции, инициализатор может быть использован в качестве значения. Например:

// Аннотация типов обязательна, так как String имеет несколько инициализаторов.
let initializer: (Int) -> String = String.init
let oneTwoThree = [1, 2, 3].map(initializer).reduce("", combine: +)
print(oneTwoThree)
// Выведет "123"

Если вы указываете тип по имени, то вы можете получить к инициализатору типа без использования самого выражения инициализатора. Во всех остальных случаях необходимо использовать выражение инициализатора.

let s1 = SomeType.init(data: 3)  // Действительный вариант
let s2 = SomeType(data: 1)       // Действительный вариант
 
let s3 = someValue.dynamicType.init(data: 7)  // Действительный вариант
let s4 = someValue.dynamicType(data: 5)       // Ошибка

Грамматика выражения инициализатора

initializer-expression → postfix-expression­init­
initializer-expression → postfix-expression­init­argument-names­

Явное выражение члена

Явное выражение члена позволяет получить доступ к членам именованного типа, кортежа, или модуля. Оно состоит из периода (.) между элементом и идентификатором его члена.

выражение.имя члена

Члены именованного типа названы как часть объявления типа или расширения. Например:

class SomeClass {
    var someProperty = 42
}
let c = SomeClass()
let y = c.someProperty  // доступ к члену

Члены кортежа неявно названы интеджерами в порядке их появления, начиная с нуля. Например:

var t = (10, 20, 30)
t.0 = t.1
// Теперь t равно (20, 20, 30)

Члены модуля получают доступ к объявлению топ-уровня этого модуля.

Для того, чтобы различать методы или инициализаторы, чьи имена отличаются только именами своих аргументов, возьмите имена аргументов в скобки, и после каждого имени аргумента поставьте двоеточие (:). Поставьте подчеркивание (_) для аргумента без имени. Для того, чтобы различать перегруженные методы, используйте аннотацию типа. Например:

class SomeClass {
    func someMethod(x: Int, y: Int) {}
    func someMethod(x: Int, z: Int) {}
    func overloadedMethod(x: Int, y: Int) {}
    func overloadedMethod(x: Int, y: Bool) {}
}
let instance = SomeClass()
 
let a = instance.someMethod              // Двусмысленно
let b = instance.someMethod(x:y:)        // Недвусмысленно
 
let d = instance.overloadedMethod        // Двусмысленно
let d = instance.overloadedMethod(x:y:)  // Двусмысленно
let d: (Int, Bool) -> Void  = instance.overloadedMethod(x:y:)  // Недвусмысленно

Если период появляется в начале строки, он понимается как часть явного выражения членов, а не как неявное выражение члена. Например, в следующем примере показаны последовательные вызовы методов, приведшие к разбиению на несколько строк:

let x = [10, 3, 20, 15, 4]
    .sorted()
    .filter { $0 > 5 }
    .map { $0 * 100 }

Грамматика явного выражения члена

explicit-member-expression → postfix-expression­decimal-digits­
explicit-member-expression → postfix-expression­identifier­generic-argument-clause­opt­
explicit-member-expression → postfix-expression­identifier­argument-names­
argument-names → argument-name­ argument-names­opt­
argument-name → identifier­

Постфиксное выражение Self

Постфиксное выражение self состоит из выражения или имени типа, сразу за которым следует .self. Выглядит вот так:

выражение.self
тип.self

Первый вариант оценивает значение выражения. Например, x.self принимает значение x.

Второй вариант определяет значение типа. Используйте эту форму для получения доступа к типу в качестве значения. Например, поскольку SomeClass.self принимает значение самого типа SomeClass, вы можете передать его функции или методу, который принимает аргумент верхнего уровня.

Грамматика выражения self

postfix-self-expression → postfix-expression­self­

Выражение динамического типа

Выражение dynamicType состоит из выражения, за которым сразу следует .dynamicType. Выглядит вот так:

выражение.dynamicType

Выражение не может быть именем типа. Полностью выражение dynamicType определяет значение типа выражения во время исполнения, как показано в следующем примере:

class SomeBaseClass {
    class func printClassName() {
        print("SomeBaseClass")
    }
}
class SomeSubClass: SomeBaseClass {
    override class func printClassName() {
      print("SomeSubClass")
    }
}
let someInstance: SomeBaseClass = SomeSubClass()
// someInstance имеет статический тип SomeBaseClass во время компиляции и
// она имеет динамический тип SomeSubClass во время исполнения
someInstance.dynamicType.printClassName()
// Выведет "SomeSubClass"

Грамматика выражения динамического типа

dynamic-type-expression → postfix-expression­dynamicType­

Выражение сабскрипта

Выражение сабскрипта обеспечивает доступ к индексу с помощью геттера и сеттера, соответствующего сабскрипту объявления. Выглядит следующим образом:

выражение[выражения индекса]

Для того, чтобы определить значение выражения сабскрипта, сабскрипт геттера для типа выражения вызывается с выражениями индекса, передаваемых в качестве параметров индекса. Для того, чтобы установить его значение, сабскрипт сеттера вызывается таким же образом.

Грамматика выражения санскрита

subscript-expression → postfix-expression­ [ ­expression-list­ 

Выражения принудительного значения

Выражение принудительного значения разворачивает опциональное значение, которое вы уверены, что не будет равно nil. Выглядит оно следующим образом:

выражение!

Если значение выражения не nil, то опционального значение разворачивается и возвращается с соответствующим неопциональным типом. В противном случае возникает ошибка во время выполнения.

Развернутое значение выражения принудительного значения может быть изменено, либо через изменение самого значения, или путем его присвоения одному из членов-значения. Например:

var x: Int? = 0
x! += 1
// x теперь 1
 
var someDictionary = ["a": [1, 2, 3], "b": [10, 20]]
someDictionary["a"]![0] = 100
// someDictionary теперь ["b": [10, 20], "a": [100, 2, 3]]

Грамматика принудительного значения

forced-value-expression → postfix-expression­

Выражение опциональной цепочки

Выражение опциональной цепочки служит для упрощенного синтаксиса и использования опциональных значений в постфиксных выражениях. Выглядит вот так:

выражение?

Постфиксный оператор ? из выражения делает выражение опциональной цепочки без изменения значения выражения.

Выражения опциональной цепочки должны появляться внутри постфиксных выражений, и благодаря им постфиксные выражения вычисляются по-другому. Если значение выражения опциональной цепочки равно nil, все другие операции в постфиксном выражении игнорируются и все постфиксное выражение приравнивается к nil. Если значение выражения опциональной цепочки не nil, то значение выражения опциональной цепочки разворачивается и используется для оценки оставшегося постфиксного выражения. В любом случае значение постфиксного выражения по-прежнему опционального типа.

Если постфиксное выражение, содержащее выражение опциональной цепочки, вложено в другие постфиксные выражения, только самое внешнее выражение возвращает опциональный тип. В приведенном ниже примере, когда c не nil, его значение разворачивается и используется для вычисления .property, значение которого используется для вычисления .performAction(). Все выражение c?.property.performAction() имеет значение опционального типа.

var c: SomeClass?
var result: Bool? = c?.property.performAction()

В следующем варианте показано поведение примера выше без использования опциональной цепочки.

var result: Bool? = nil
if let unwrappedC = c {
   result = unwrappedC.property.performAction()
}

Развернутое значение выражения опциональной цепочки может быть изменено, либо через изменение самого значения, или через присвоение к одному из членов значения. Если значение выражения опциональной цепочки равно nil, выражение в правой части оператора присваивания не вычисляется. Например:

func someFunctionWithSideEffects() -> Int {
   return 42  // фактически никаких побочных эффектов не имеет
}
var someDictionary = ["a": [1, 2, 3], "b": [10, 20]]
 
someDictionary["not here"]?[0] = someFunctionWithSideEffects()
// someFunctionWithSideEffects не вычисляется
// someDictionary все еще ["b": [10, 20], "a": [1, 2, 3]]
 
someDictionary["a"]?[0] = someFunctionWithSideEffects()
// someFunctionWithSideEffects вычисляется, возвращается 42
// someDictionary теперь равно ["b": [10, 20], "a": [42, 2, 3]]

Грамматика выражения опциональной последовательности

optional-chaining-expression → postfix-expression­

Swift: 
3.0