Как и зачем использовать Labeled Statements в Swift?

iOS_Deep_4.6_site-5020-e3061e.png

Перед написанием данной статьи я спросил в нескольких iOS-чатах про эту фичу Swift, однако никто из iOS-разработчиков вообще(!) не знал о существовании Label Statements. В одной из прошлых заметок, где мы разбирали, какие есть типы Предписаний (Statements) в Swift, были упомянуты Control Flow Statements. Вот именно на управляющие потоком выполнения предписания и можно поставить лейблы.

Зачем?

Некоторые сравнивают Label Statements с некоторой «огламуренной» разновидностью GOTO. Нагляднее всего это можно показать на двух вложенных Control Flow Statements, например на циклах:

let arrVeggies = ["eggplant", "cauliflower", "potato"]
let arrColors = [0xffffff, 0x000000]

vegLabel: for veg in arrVeggies {
    print(veg)
    for col in arrColors {
        if veg == "cauliflower" && col == 0x000000 {
            continue vegLabel
        }
        print(String(col, radix: 16))
    }
}

Перед первым циклом мы вставили vegLabel. Это дало нам возможность вызвать во втором цикле continue vegLabel, что продолжило выполнение arrVeggies. В итоге мы получили такой результат:

eggplant
ffffff
0
cauliflower
ffffff
potato
ffffff
0

На реальных проектах таким образом вы сможете оптимизировать производительность сложных вложенных циклов.

Давайте ещё рассмотрим пример с break

Работая в геймдеве, мне часто приходилось обходить 2-х мерные массивы, которые являются представлением 2D карты:

// ┌──▶ x
// │
// ▼
// y
let treasureIsland4x4 = [
["empty", "empty", "empty", "empty"],
["empty", "empty", "empty", "empty"],
["empty", "empty", "empty", "empty"],
["treasure", "empty", "empty", "empty"]
]

yScan: for (y, xRow) in treasureIsland4x4.enumerated() {
    // x Scan
    for (x, value) in xRow.enumerated() {
        if value == "treasure" {
            print("Found at x=\(x), y=\(y)")
            break yScan
        }
    }
}

Результат будет:

Found at x=0, y=3

Массив мы предопределили литералами и «закопали» сокровище в начале последнего вложенного x массив. Если во вложенном цикле мы напишем break, то мы просто выйдем из x Scan цикла и нам придётся писать или условие со вторым break, или отдельную функцию с return.

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

Кроме циклов, лейблы можно ставить и на другие Control Flow Statements: На while-циклы:

whileLabel: while condition == true {
    
}

На repeat-while-циклы:

repeatLabel: repeat {
    
} while condition == true

На if-предписание:

ifLabel: if condition == true {
    
}

На switch-предписание:

switchLabel: switch condition {
    
}

Остались вопросы? Пишите их в комментариях!

Автор
0 комментариев
Для комментирования необходимо авторизоваться