Analysis of problem A of the qualifying stage of Yandex Cup 2023 – iOS
Preface
The qualifying stage of the Yandex Cup for developers in various areas recently ended, one of which was mobile development for iOS. Let’s talk about it, or rather about the tasks that were presented there. It is worth noting that their complexity is above average, for this reason, I think everyone will emphasize something new for themselves. I would like to immediately say that some of the constructs/tools of the language/frameworks used were not new to me, but I rarely encountered them in my life, so I had to read and practically reproduce the code from the condition, experimenting with it. I didn’t have the right answers, and I decided after the end of the qualifying stage. If you notice any inaccuracies in the wording, thoughts, or answers, I will be happy to discuss this in the comments.
Let’s get started!)
Condition
Possible answers:
operator must be postfix
@escaping in a declaration is redundant
@autoclosure in a declaration is redundant
throws in a declaration is redundant
the type of the variable v in this case is the type of the non-optional (Wrapped) value
this code will not compile
Wrapped in this example is a generic type
for such a declaration you need to declare your own error type instead of the Error type
without explicitly specifying a precedence group, the operator will be declared with DefaultPrecedence
My final answer:
Spoiler
@escaping in the declaration is redundant
Wrapped in this example is a generic type
without explicitly specifying a precedence group, the operator will be declared with DefaultPrecedence
Analysis of answer No. 1 (the operator must be postfix)
Swift has the ability to create “Custom Operators” using the “operator” keyword
The operator itself can be in one of three positions, which are determined by modifiers: prefix (before the operand), infix (between the operands), postfix (after the operand)
In this case, a custom operator is defined at the global level:
infix operator !!
The Optional extension implements the enumeration function itself, which takes several parameters:
v: Self,
e: @escaping @autoclosure () -> Error
Therefore, there cannot be a postfix modifier here, as well as a prefix modifier, since they work with one operand.
Analysis of answer No. 2 (redundant in the ad):
@escaping is an unnamed function attribute (colloquially “closure”) that is used to change the lifecycle of a closure, allowing it to “escape” after the function to which it was passed completes
Actually, in this example, we don’t need to mark our closure with the @escaping attribute, since we don’t need it outside of this function
Analysis of answer No. 3 (redundant in the ad):
@autoclosure is another closure attribute that allows you to convert the passed value (function argument) to the corresponding return type (in our case, the type that implements the Error protocol) autoclosure
In this case, the @autoclosure attribute is not redundant, you can leave it (but it is better not to use it, as it reduces the readability of the code)
Analysis of answer No. 4 (throws in the ad is redundant):
The body of the method states that we are throwing an exception using the “throw” keyword:
throw e()
It turns out that when declaring a function, we must indicate that it throws exceptions that need to be handled:
) throws -> Wrapped
Analysis of answer No. 5 (the type of the variable v in this case is the type of a non-optional (Wrapped) value):
If the type of the variable v were non-optional (Wrapped), then there would be no point in this method, since it just “reveals” the optional one (Wrapped).
Analysis of answer No. 6 (this code will not compile):
There’s no reason why it shouldn’t compile.
Analysis of answer No. 7 (Wrapped in this example is a generic type):
Yes, Wrapped is a generic type, since we cannot unambiguously say what type the function’s return value is.
Analysis of answer No. 8 (for such a declaration you need to declare your own error type instead of the Error type):
In general, this can be done, but it is not necessary. We simply must pass an object whose type implements the Error protocol as the closure’s return value.
Analysis of answer No. 9 (without explicitly specifying the precedence group, the operator will be declared with DefaultPrecedence):
By default, if we do not specify precedence group, then the operator will be declared with 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 thanTernaryPrecedence
.