Предисловие

Недавно закончился отборочный этап Yandex Cup для разработчиков по различным направлениям, одним из которых была мобильная разработка под iOS. Как раз про нее и поговорим, а точнее про задания, которые были там представлены. Стоит отметить, что их сложность выше среднего, по этой причине, думаю, каждый подчеркнет для себя что-нибудь новое. Хотелось бы сразу сказать о том, что некоторые используемые конструкции/инструменты языка/фреймворков были для меня не новы, но в жизни встречался с ними редко, поэтому приходилось читать и на практике воспроизводить код из условия, экспериментируя с ним. Правильных ответов у меня не было, и решал я уже после окончания отборочного этапа. Если заметите какие-либо неточности в формулировках, в размышлениях, в ответах, буду рад обсудить это в комментариях.

Приступим!)

Условие

Yandex Cup 2023, qualifying stage, task A

Варианты ответов:

  1. оператор должен быть postfix

  2. @escaping в объявлении избыточен

  3. @autoclosure в объявлении избыточен

  4. throws в объявлении избыточен

  5. тип переменной v в данном случае является типом неопционального(Wrapped) значения

  6. данный код не скомпилируется

  7. Wrapped в данном примере является generic типом

  8. для такого объявления нужно объявить собственный тип ошибки вместо типа Error

  9. без явного задания precedence group оператор будет объявлен с DefaultPrecedence

Мой итоговый ответ:

Спойлер
  1. @escapingв объявлении избыточен

  1. Wrapped в данном примере является generic типом

  1. без явного задания precedence group оператор будет объявлен с DefaultPrecedence

Разбор ответа №1 (оператор должен быть postfix)

В языке Swift имеется возможность создавать "Пользовательские операторы", используя ключевое слово "operator"

Сам оператор может находиться в одной из трех позиций, которые определяются модификаторами: prefix (перед операндом), infix (между операндами), postfix (после операнда)

В данном случае на глобальном уровне определяется пользовательский оператор:

infix operator !!

В расширении Optional-а реализована функция самого перечисления, которая принимает несколько параметров:

v: Self,
e: @escaping @autoclosure () -> Error

Следовательно модификатора postfix здесь быть не может, как и модификатора prefix, так как они работают с одним операндом.

Разбор ответа №2 (@escaping в объявлении избыточен):

@escaping— это атрибут безымянной функции (в простонародье "closure"), который используется для изменения жизненного цикла замыкания, позволяя ему "сбежать" после завершения функции, в которую он был передан

Собственно, в данном примере нам не за чем помечать наш closure атрибутом @escaping , так как он нам не нужен вне данной функции

Разбор ответа №3 (@autoclosure в объявлении избыточен):

@autoclosure— это ещё один из атрибутов замыкания, который позволяет преобразовать передаваемое значение (аргумент функции) в соответствующее возвращаемому типу (в нашем случае типу, реализующему протокол Error) автозамыкание

В данном случае атрибут @autoclosureне избыточен, его можно оставить (но лучше его не использовать, так как он снижает читаемость кода)

Разбор ответа №4 (throws в объявлении избыточен):

В теле метода указано, что мы выбрасываем исключение, используя ключевое слово "throw":

throw e()

Получается и при объявлении функции мы обязаны указать, что она выбрасывает исключения, которые необходимо обработать:

) throws -> Wrapped

Разбор ответа №5 (тип переменной v в данном случае является типом неопционального(Wrapped) значения):

Если бы тип переменной v был неопциональным(Wrapped), то и смысла в этом методе не было бы, так как он как раз таки и "раскрывает" опциональный(Wrapped).

Разбор ответа №6 (данный код не скомпилируется):

Нет причин, по которым он не должен компилироваться.

Разбор ответа №7 (Wrapped в данном примере является generic типом):

Да Wrapped является generic типом, так как мы не можем однозначно сказать какой тип у возвращаемого значения функции.

Разбор ответа №8 (для такого объявления нужно объявить собственный тип ошибки вместо типа Error):

В целом, это можно сделать, но это необязательно. Мы просто должны в качестве возвращаемого значения замыкания передать объект, тип которого реализует протокол Error.

Разбор ответа №9 (без явного задания precedence group оператор будет объявлен с DefaultPrecedence):

По умолчанию, если мы не задаем precedence group, то оператор будет объявлен с DefaultPrecedence:

The infix operators are grouped below by precedence group in decreasing order of precedence. If you declare a new operator without specifying a precedence group, it is a member of the DefaultPrecedence precedence group. DefaultPrecedence has no associativity and a precedence immediately higher than TernaryPrecedence.

Почитать можно тут

Авторы

Сергей А.

Middle iOS-developer, стажер-исследователь НУЛ ОиМТ ДПИ ФКН НИУ ВШЭ