воскресенье, 14 августа 2016 г.

Swift 3.0 и цикл for

В версии 3.0 языка Swift решили убрать и, таки, убрали некоторый синтаксис языка C. В частности, убрали вид цикла for, принятый в языке C. Убрали вместе с замечательными операциями ++ и --. К чему это нас приводит? Это приводит к тому, что простой цикл вида:
for var i = 0; i < N; ++i {
    rint("\(i)")

}
использовать нельзя. Но тогда что в замен? В замен Swift давно предлагает диапазоны. По планам разработчиков, все пользователи Swift должны были писать так:
for i in 0..<10 {
    print("\(i)")

}
Вполне хороший синтаксис. Но может ли он покрыть все возможности старого? Хотя бы все важные возможности. Например, что делать, когда надо посчитать значения функции на заданном отрезке с некоторым шагом? В синтаксисе C можно записать так:
for var x = a; x <= b; x += h {
    print("y(\(x)) = \(x*x)")
}
Прежде, чем дать решение поставленной задачи, разберем, какие возможности есть у диапазонов и как они покрывают задачи, решаемые циклом for. Уже показан пример перебора элементов из возрастающего диапазона. Но у нас есть и убывающий:
for var i = 9; i >= 0; i-- {
    print(i)
}
Такое решение задачу не решит:

for i in 9...0 {
    print("\(i)")
}
Будет выдана ошибка времени исполнения, говорящая, что начало диапазона не должно быть больше конца. Для прохождения в обратном направлении надо применить функцию reversed():

for i in (0..<10).reversed() {
    print("\(i)")
}
Для случая с произвольным шагом вроде:
for var i = 0; i < 10; i += 2 {
    print(i)
}
можно написать следующее:

for i in stride(from: 0, to: 10, by: 2) {
    print(i)
}
Такая запись:

for i in 0.stride(to: 10, by: 2) {
    print(i)
}
пока не доступна и верно доступна не будет.
Этот вариант позволяет решить поставленную выше задачу таким образом:
for x in stride(from: a, to: b, by: h) {
    print("y(\(x)) = \(x*x)")
}
Таким образом понятно, что новый синтаксис перекрывает основные возможности оператора for в синтаксисе C. Однако, ещё не рассмотрен вопрос прохождения по элементам массива. Задачи такого рода можно и, вероятно, нужно решать особым способом – перебором элементов коллекции. Рассмотрим на примерах. Перепишем следующий пример в новом синтаксисе:
let arr = [2, 3, 45, 6, 8, 83, 100]

for var i = 0; i < arr.count; i++ {
    print(arr[i])
}
С применением цикла:
let arr = [2, 3, 45, 6, 8, 83, 100]

// В прямом направлении 
for el in arr{
    print(el)
}

// В обратном направлении 
for el in arr.reversed(){
    print(el)
}
В случае, если нам требуются работать с индексами коллекции следующий вариант не является лучшим:

for i in 0..<arr.count {
    print(arr[i])
}
В замен используем такой подход:
for i in arr.indices {
    print(arr[i])
}

for (i, el) in arr.enumerated() {
    print("\(i\(el)")
}
Вроде всё хорошо и охвачены все задачи, коие требуется решать наиболее часто. И тут мы следует вспомнить, что в Swift добавлены некоторые черты функционального языка. И работа с коллекциями одно из тех мест, где уместно их использовать. Например, таким образом:
arr.forEach{
    print( $0 )
}

arr.reversed().forEach{
    print( $0 )
}


arr.enumerated().forEach {
    (i, el) in
    print("\(i)   \(el)")
}
Да, у нас есть набор удобных функций над коллекциями народе map, flatMap, filter, reduce. Так что не забываем ими пользоваться.

суббота, 13 августа 2016 г.

Система сборки языка Swift.

В язык Swift добавили систему сборки начиная с версии 3.0, которая основана на пакетах. Подробнее описание и об использование написано здесь https://swift.org/package-manager/#example-usage. Здесь я кратко опишу применение системы.
Созданный проект должен иметь определенную структуру. В каталоге проекта находиться файл Packages.swift. В нем содержится конфигурация сборки проекта.  Все исходные коды находятся в подкатологе проекта с названием source. Для определения точки входа обязателен файл с названием main.swift.
Сборка приложения, при использовании данной системы, происходит по команде swift build, выполненной  в каталоге проекта.
Управление особенностями сборки для целевой платформы осуществляется конструкциями, похожими на директивы препроцессора языка C. Например,  #if, #else, #endif.
#if os(Linux)
import Glibc
#else
import Darwin.C 
#endif
Зависимости описываются в файле Packages.swift. Причем, для описания используется язык Swift. При указании зависимостей можно сослаться на какое-либо хранилище, например GitHub.

import PackageDescription

let package = Package (
    name: "swiwt3Test",
    target: [],
    dpendencies: []
)