Обновить
3
0
Ярослав Пастернак@Thorax

iOS dev

Отправить сообщение

Немного о функторах и функциях высшего порядка в Swift

Время на прочтение3 мин
Охват и читатели19K

Коллекции


Разработчики, перешедшие на Swift с Objective-C, не могли не заметить удобнейший функционал, который предоставляет Swift для работы с коллекциями. Использование диапазонов в индексах
let slice = array[1..<10]
удобный синтаксис инициализации и добавления элемента в коллекцию, расширяемость, и, конечно функции высшего порядка

Filter


Самой часто используемой функцией для коллекций, пожалуй, является filter
let alex = Person(name: "Alex", age: 23)
let jenny = Person(name: "Jenny", age: 20)
let jason = Person(name: "Jason", age: 35)
let persons = [alex, jenny, jason]
let jNamedPersons = persons.filter { $0.name.hasPrefix("J") } // [jenny, jason]


Reduce


Реже используемой, но при этом крайне выразительной и удобной является функция reduce

let ages = persons.map{ Float($0.age) }
let average = ages.reduce(0, +) / Float(persons.count)


Можно писать свои функции высшего порядка и это довольно увлекательно:
func divisible(by numbers: Int...) -> (Int) -> Bool {
    return { input -> Bool in
        return numbers.reduce(true) { divisible, number in
            divisible && input % number == 0
        }
    }
}

let items = [6, 12, 24, 13]
let result = items.filter(divisible(by: 2, 3, 4)) // [12, 24]


Map


Функциональные понятия функторов и монад пришли к нам из языка Haskell. Говорят, невозможно просто взять и понять, что такое монада, а уж тем более невозможно это объяснить. Тем не менее мы можем временно отбросить все сложности и объяснить себе только то, что действительно необходимо, а те, кто захочет закопаться поглубже, могут начать с изучения Haskell.

Итак, для простоты мы можем считать, что функтор это контейнер, к которому применима функция map, а монада это функтор, к которому применима функция flatMap.

Поскольку коллекции это контейнеры, и в Swift для них определена функция map, они могут выступать в роли функторов:
для того, чтобы трансформировать коллекцию одного типа в коллекцию другого типа, возьмем наш массив persons и получим из него массив возрастов типа [Int]
let ages = array.map{ $0.age } // [23, 20, 35]


FlatMap


И в роли монад:
для того, чтобы из массива oprtional типов вернуть массив не опциональных значений
let optionalStrings: [String?] = ["a", nil, "b", "c", nil]
let strings = optionalStrings.flatMap { $0 } // ["a", "b", "c"]

для того, чтобы расширить первоначальную коллекцию
let odds = [1,3,5,7,9]
let evensAndOdds = odds.flatMap { [$0, $0 + 1] } // [1,2,3,4,5,6,7,8,9,10]

Читать дальше →

UIColor и UIImage в Xcode 8 при помощи литералов

Время на прочтение2 мин
Охват и читатели12K

Работа с UIImage и UIColor из кода была не слишком удобной, потому что трудно представить себе цвет UIColor(red: 0.2, green: 0.4, blue: 0.6, alpha: 1) или UIImage(named: "pattern25"), если ты не дизайнер, конечно.


Для меня было чудом то, что Apple сделали в последних версиях Playground, а именно


  • Возможность указывать цвет, выбирая из палитры цветов:

image


  • Возможность выбирать изображение из тех, что находятся в ресурсах:

image


Цвет представлен очень наглядно и при клике на него, можно узнать какие значения RGBA он имеет и подтюнить его по необходимости.


Миниатюры картинок тоже выглядят гораздо нагляднее, чем просто названия ресурсов. К тому же инициализируя UIImage при помощи failable initializer init(named: String) -> UIImage? мы рискуем получить nil, неправильно указав имя ресурса. Литералы же всегда возвращают значение.

Читать дальше →

Информация

В рейтинге
Не участвует
Откуда
Санкт-Петербург, Санкт-Петербург и область, Россия
Дата рождения
Зарегистрирован
Активность