[Разработка под iOS, Swift] Создание пользовательских функций запросов с key paths (перевод)
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Поскольку это довольно строгий статически компилируемый язык, с первого взгляда может показаться, что Swift мало чего может предложить в плане кастомизации синтаксиса, но на самом деле это далеко не так. Благодаря таким фичам, как настраиваемые и перегруженные операторы, key paths, function/result builders и т. д., у нас есть множество возможностей для настройки синтаксиса Swift под конкретные сценарии использования.Конечно, можно определенно утверждать, что к любому виду кастомизации синтаксиса следует подходить с большой осторожностью, поскольку нестандартный синтаксис может легко стать источником путаницы, если мы не будем достаточно осторожны. Но в определенных ситуациях этот компромисс может вполне того стоить и может позволить нам создавать что-то вроде «микро-DSL», которые на самом деле могут помочь нам сделать наш код более понятным, а не наоборот.Инвертированные логические key pathsЧтобы рассмотреть один из таких случаев, предположим, что мы работаем над приложением для управления, фильтрации и сортировки статей, которое имеет следующую модель данных (Article):
struct Article {
var title: String
var body: String
var category: Category
var isRead: Bool
...
}
Теперь предположим, что очень распространенной задачей в нашей кодовой базе является фильтрация различных коллекций, каждая из которых содержит экземпляры указанной выше модели. Один из способов сделать это - использовать тот факт, что любой key path литерал Swift может быть автоматически преобразован в функцию, что позволяет нам использовать следующий компактный синтаксис при фильтрации по любому логическому свойству, например в данном случае isRead:
let articles: [Article] = ...
let readArticles = articles.filter(\.isRead)
Это действительно здорово, однако приведенный выше синтаксис можно использовать только тогда, когда мы хотим сравнить с true - это означает, что если бы мы хотели создать аналогично отфильтрованный массив, содержащий все непрочитанные статьи, нам пришлось бы использовать вместо этого замыкание (или передавать функцию):
let unreadArticles = articles.filter { !$0.isRead }
Это, конечно, не очень большая проблема, но если описанные выше операции выполняются во многих разных местах нашей кодовой базы, тогда мы можем начать спрашивать себя: «А было бы здорово, если бы мы могли также использовать тот же красивый key path синтаксис для инвертированных логических значений? "Здесь на помощь приходит концепция кастомизации синтаксиса. Реализуя следующую префиксную функцию, мы фактически можем создать небольшую настройку, которая позволит нам использовать key path независимо от того, сравниваем ли мы с true или false:
prefix func !<T>(keyPath: KeyPath<T, Bool>) -> (T) -> Bool {
return { !$0[keyPath: keyPath] }
}
Вышеупомянутое, по сути, является перегрузкой встроенного префиксного оператора !, который позволяет применить этот оператор к любому Bool key path, чтобы превратить его в функцию, которая инвертирует (или переворачивает) его значение, что, в свою очередь, теперь позволяет нам обработать наш массив unreadArticles следующим образом:
let unreadArticles = articles.filter(!\.isRead)
Это довольно круто и не делает наш код непонятнее, учитывая, что мы используем оператор ! таким образом, который соответствует тому, как он используется по умолчанию - для отрицания логического выражения.Сравнение на основе key paths Мы можем пойти еще дальше и также сделать возможным использование key paths для формирования фильтрующих запросов, которые сравнивают данное свойство с любым видом значения Equatable. Это стало бы полезным, если бы мы, например, захотели иметь возможность отфильтровать массив Equatable по каждой категории (category) статьи. Тип этого свойства, Category, в настоящее время определяется как enum, который выглядит следующим образом:
extension Article {
enum Category {
case fullLength
case quickReads
case basics
...
}
}
Точно так же, как мы ранее уже перегружали ! с key path специфичным вариантом, мы можем сделать то же самое с оператором ==, и, как и раньше, мы вернем возвращающее Bool замыкание, которое затем может быть напрямую передано в API по типу filter:
func ==<T, V: Equatable>(lhs: KeyPath<T, V>, rhs: V) -> (T) -> Bool {
return { $0[keyPath: lhs] == rhs }
}
С учетом вышеизложенного теперь мы можем легко фильтровать любую коллекцию, используя сравнение на основе key path, например:
let fullLengthArticles = articles.filter(\.category == .fullLength)
ЗаключениеВ зависимости от того, кого вы спрашиваете, тот факт, что Swift позволяет нам легко создавать указанные выше функциональные возможности с помощью пары легких перегрузок, может оказаться либо действительно потрясающим, либо невероятно тревожным. Я склоняюсь к тому, что истина где-то посредине, и думаю, что это действительно здорово, что мы можем вносить незначительные доменно-ориентированные изменения в синтаксис Swift. Но в то же время я думаю, что эти изменения всегда следует вносить с целью сделать наши код проще, а не сложнее.Как и все, о чем я пишу здесь, на Swift от Sundell, я лично использовал. Я использовал вышеупомянутую технику в нескольких проектах, в которых мне приходилось много фильтровать коллекции, и она проявила себя замечательно, но я бы не стал ее использовать, если бы только у меня не было сильной потребности в такой функциональности.Чтобы получить более подробный и более продвинутый вариант описанной выше техники, ознакомьтесь с разделом «Предикаты в Swift» и не стесняйтесь присылать мне свои вопросы и комментарии через Twitter или по электронной почте.Перевод статьи был подготовлен в преддверии старта курса "IOS Developer. Professional".
- Насколько востребованы iOS-разработчики в период кризиса?
- Какие требования к соискателям предъявляют компании-работодатели?
- Какие вопросы задают на собеседовании, и как не допустить ошибку при ответе?
- Какие знания и навыки необходимы, чтобы выделиться из толпы и обеспечить себе карьерный прогресс?
На все эти вопросы, в рамах бесплатного карьерного вебинара, ответит наш эксперт - Ексей Пантелеев. Также Ексей подробно расскажет о программе курса и процессе обучения. Записаться на вебинар.
===========
Источник:
habr.com
===========
===========
Автор оригинала: Sundell
===========Похожие новости:
- [Программирование, Java] Шпаргалка по Spring Boot WebClient (перевод)
- [Data Engineering] Что такое фильтр Блума? (перевод)
- [Математика] Новые квантовые алгоритмы, совершившие прорыв в нелинейных уравнениях (перевод)
- [SQLite, Xcode, Swift] Видеомонтаж, машинное обучение и взломанный xml — все в одной программе
- [Разработка под iOS, Компьютерное железо, IT-компании] Apple повысила купон за возврат комплекта разработчика Apple Silicon до $500 и расширила условия его использования
- [MySQL, Администрирование баз данных] Советы по хранению Percona Backup в облаке (перевод)
- [Программирование, Go] Создаем бессерверное приложение с помощью Azure Functions и Go (перевод)
- [Agile, Управление продуктом] Цель продукта – это промежуточная стратегическая цель (перевод)
- [Высокая производительность, Разработка под iOS, Разработка мобильных приложений, Разработка под Android, Микросервисы] Envoy как универсальный сетевой примитив
- [Разработка под iOS, IT-компании] Apple попросила разработчиков вернуть DTK с чипом Apple A12Z в обмен на купон в $200. Оборудование они получили за $500
Теги для поиска: #_razrabotka_pod_ios (Разработка под iOS), #_swift, #_key_paths, #_operators, #_swift, #_blog_kompanii_otus (
Блог компании OTUS
), #_razrabotka_pod_ios (
Разработка под iOS
), #_swift
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 19:18
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Поскольку это довольно строгий статически компилируемый язык, с первого взгляда может показаться, что Swift мало чего может предложить в плане кастомизации синтаксиса, но на самом деле это далеко не так. Благодаря таким фичам, как настраиваемые и перегруженные операторы, key paths, function/result builders и т. д., у нас есть множество возможностей для настройки синтаксиса Swift под конкретные сценарии использования.Конечно, можно определенно утверждать, что к любому виду кастомизации синтаксиса следует подходить с большой осторожностью, поскольку нестандартный синтаксис может легко стать источником путаницы, если мы не будем достаточно осторожны. Но в определенных ситуациях этот компромисс может вполне того стоить и может позволить нам создавать что-то вроде «микро-DSL», которые на самом деле могут помочь нам сделать наш код более понятным, а не наоборот.Инвертированные логические key pathsЧтобы рассмотреть один из таких случаев, предположим, что мы работаем над приложением для управления, фильтрации и сортировки статей, которое имеет следующую модель данных (Article): struct Article {
var title: String var body: String var category: Category var isRead: Bool ... } let articles: [Article] = ...
let readArticles = articles.filter(\.isRead) let unreadArticles = articles.filter { !$0.isRead }
prefix func !<T>(keyPath: KeyPath<T, Bool>) -> (T) -> Bool {
return { !$0[keyPath: keyPath] } } let unreadArticles = articles.filter(!\.isRead)
extension Article {
enum Category { case fullLength case quickReads case basics ... } } func ==<T, V: Equatable>(lhs: KeyPath<T, V>, rhs: V) -> (T) -> Bool {
return { $0[keyPath: lhs] == rhs } } let fullLengthArticles = articles.filter(\.category == .fullLength)
=========== Источник: habr.com =========== =========== Автор оригинала: Sundell ===========Похожие новости:
Блог компании OTUS ), #_razrabotka_pod_ios ( Разработка под iOS ), #_swift |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 19:18
Часовой пояс: UTC + 5