[Перевод] Swift 2.2. Важнейшие нововведения

Здравствуйте, уважаемые читатели!

Спасибо, что практически смели с полок нашу экспериментальную книгу по языку Swift. Серьезно обдумываем допечатку в апреле, консультируемся с автором насчет обновлений, а также подыскиваем другие, более фундаментальные книги. В ходе этих поисков довелось познакомиться с отличной статьей, которую можно было бы назвать «Что Swift грядущий нам готовит». Ее перевод найдете под катом.

Приятного чтения!

Выход языка Swift 2.2 запланирован вместе с выпуском Xcode 7.3 и должен состояться в период с марта по май 2016. Эта версия позиционируется как промежуточная между Swift 2 и Swift 3 и предполагает немало изменений. В принципе, Swift 2.2 просто предупреждает вас об изменениях, тогда как Swift 3 не позволит делать многих вещей, к которым вы привыкли. Но не волнуйтесь — думаю, это очередной важный шаг, который поможет сделать Swift еще свифтее.

Здесь я упомяну несколько важнейших изменений, планируемых в Swift. Можете опробовать их прямо сейчас, скачав демонстрационную версию Swift 2.2, которая будет работать с Xcode 7.2 и 7.3-бета, если немного похимичить. Предварительно потребуется просто познакомиться с последней версией Swift, описанной на официальном сайте.

Операторы

В Swift 2.2 не будет операторов ++ и --. На первый взгляд меня это возмутило, но, фактически, в современном Swift они уже просто не нужны. Необходимость в инкрементах отпадает благодаря новому циклу for и функциям высшего порядка вроде map или filter. Разумеется, вы по-прежнему можете реализовывать инкремент сами, но уже иным способом.

func plusPlus() {
    var i = 0
    i++ // ВНИМАНИЕ: '++' нежелателен: в Swift 3 от него планируется избавиться
    i += 1 // '+=' и '-=' применяется для целочисленных типов или чисел с плавающей точкой 
 
    // succesor() и predecessor() применяются с индексными типами
    let alphabet = "abcdefghijklmnopqrstuvwxyz"
    let index = alphabet.characters.indexOf("u")
    if let index = index {
        alphabet.characters[index.successor()]
    }
}

Крис Латтнер считает, что эти операторы инкремента/декремента лишь вносят путаницу, особенно если существуют сразу в двух формах: префиксной и постфиксной. На самом деле, я и не помню, когда в последний раз приходилось использовать ++x, поэтому если от них избавиться, то Swift, возможно, упростится в изучении как первый язык программирования.

C-подобные циклы

Такие унаследованные циклы — еще одна вещь, заимствованная из C. Удаляя for init; comparison; increment {}, мы также можем с легкостью удалить ++ и --. Но не переживайте — в Swift есть отличный и очень удобный цикл for-in.

func forLoop() {
    // ВНИМАНИЕ: C-подобная инструкция for нежелательна
    // и будет удалена в следующей версии Swift
    for var i = 1; i <= 10; i += 1 {
        print("I'm number \(i)")
    }
    
    // Инновационный стиль Swift работает нормально:
    for i in 1...10 {
        print("I'm number \(i)")
    }
}


Срезы

Вот чего я ждал целую вечность. Массивы в Swift 2.2 имеют функцию removeFirst()
. Ее можно было без труда написать и самому в качестве расширения, но теперь она предоставляется из коробки. Функция очень умная, и, даже хотя ваш массив может быть переполнен опционалами, она просто удаляет первый элемент, а не оставляет его в виде nil
. Обожаю.

func slices() {
    var array = ["First", "Second", "Third", "Fourth"]
    array.removeLast() // она существовала всегда, но…
    array.removeFirst() // родилась заново (каждый n-ный элемент становится n-1)
}

Сравнение кортежей

Может быть, это и не сенсация, но странно, что такая возможность до сих пор отсутствовала. В Swift 2.2 и далее можно сравнивать кортежи, содержащие до 6 элементов Equatable
.

func tuples() {
    let tuple1 = (1, true, 3, 4, 5, "a")
    let tuple2 = (1, false, 3, 4, 5, "a")
    let equalTuples = tuple1 == tuple2
    print(equalTuples) // false
}

Больше никакого карринга

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

// ВНИМАНИЕ: синтаксис объявления каррированных функций будет упразднен 
// в новой версии Swift; пользуйтесь списком с одним параметром
func noMoreCurryingThisWay(a: Int)(b: Int) -> Int {
    return a + b
}
 
func curryThisWay(a: Int) -> (Int) -> Int {
    return { (b: Int) -> Int in
        return a + b
    }
}


Проверка версии Swift

Очень интересная возможность, правда, надеюсь, не придется часто ею пользоваться. Я предпочитаю рефакторить код, совместимый со Swift 2, до Swift 2.2, а не поддерживать сразу две (или более) версий. Но в некоторых случаях эта возможность может пригодиться (например, пишем каркас, который должен работать и с 2.0, и с 2.2 — а, возможно, даже с 3.0). Попробуйте.

func swiftVer() {
    var cuteNumber = 7
    #if swift(>=2.2)
        print("Good morning, I'm brand new Swift")
        cuteNumber += 1
    #else
        print("Hi, I'm elder than my brother, but can ++")
        cuteNumber++
    #endif
    
    // Такой стыд, '#if swift' выглядит как старомодный макрос из Obj-C,
    // а не по-свифтовски как '#available'. Обратите внимание на этот префикс '#'.
    // Выглядит старомодно, а я хотел бы, чтобы было вот так:
    /*
     
    if #swift(>=2.2) {
    } else {
    }
     
    */
}

Селектор

Еще один макро-прием, которого я избегаю. В Swift 2.2 нельзя указывать селектор как строку. В открытом обсуждении был выбран вариант #selector
, а не Selector()
, что напоминает создание экземпляра (и также нежелательно). Фактически, этот вариант все равно лучше, чем просто строка, благодаря автозаершению; вероятность опечатки минимальна.

func selector() {
    let button = UIButton()
    // ВНИМАНИЕ: использование строкового литерала для селекторов Objective-C
    // нежелательно; вместо этого используйте '#selector' 
    button.addTarget(self, action: "forLoop", forControlEvents: .TouchUpInside)
    
    // На самом деле '#selector' работает нормально
    button.addTarget(self, action: #selector(forLoop), forControlEvents: .TouchUpInside)
}

Заключение

Это не все изменения, ожидаемые в Swift 2.2, но, на мой взгляд, наиболее важные. Рекомендую заглядывать в официальный свифтовский журнал изменений (правда, на деле это всего лишь «дорожная карта») и в раздел swift-evolution на GitHub Apple, где озвучиваются все предложения об эволюции языка.

Меня очень вдохновляет такое развитие событий, я предвкушаю грядущие изменения. Swift современный и крутой. Приходится быть современным, если хочешь перерасти Obj-C. Нужна решимость, чтобы избавиться от этих C-подобных циклов, использующихся с 1972 года. Будем надеяться на лучшее!

© Habrahabr.ru