Then

В Kotlin есть scope-функции1 — функции, позволяющие запустить блок кода в контексте объекта. В Swift такого механизма нет, но его можно сделать самостоятельно или взять готовый.

Как это работает в Kotlin? Давайте рассмотрим простой пример. Предположим, у нас есть дерево, которое выглядит так:

class TreeNode(var `val`: Int) {
    var left: TreeNode? = null
    var right: TreeNode? = null
}

И нам бы хотелось объявить всё необходимое нам дерево “за один раз”. Scope-функция apply() поможет нам это сделать:

TreeNode(1).apply {
    left = TreeNode(2)
    right = TreeNode(3)
}

Что нам потребуется, чтобы привнести похожее поведение в Switf? В целом, сделать это не сложно. Можно создать extension со следующим методом:

public func then(_ block: (Self) throws -> Void) rethrows -> Self {
    try block(self)
    return self
}

Использоваться этот фрагмент будет следующим образом:

public class TreeNode {
    public var val: Int
    public var left: TreeNode?
    public var right: TreeNode?

    init(val: Int) {
        self.val = val
    }
}

extension TreeNode {
    public func then(_ block: (Self) throws -> Void) rethrows -> Self {
        try block(self)
        return self
    }
}

Теперь мы можем собрать дерево (или любой более сложный объект), один раз описав его инициализацию:

let tree = TreeNode(val: 1).then { it in
    it.left = TreeNode(val: 2).then { it in
        it.left = TreeNode(val: 5)
        it.right = TreeNode(val: 7)
    }
    it.right = TreeNode(val: 3)
}

Но на самом деле за нас уже подумали и всё сделали заранее. Весь сахар, описанный выше, хорошо умеет делать библиотека Then2. Устанавливается она так же просто, как и все зависимости:

...
    dependencies: [
        .package(url: "https://github.com/devxoul/Then", exact: "3.0.0"),
    ],
...

Не забудьте добавить саму зависимость в цель сборки:

...
        .target(
            name: "Solution",
            dependencies: ["Then"]
        ),
...

Если работаете не со встроенными типами, добавьте к вашему собственному расширение Then:

extension ListNode: Then {}