[Перевод] 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 года. Будем надеяться на лучшее!