Ответ 1
Вы правы, опционы могут быть болью, поэтому вы не должны злоупотреблять ими. Но они больше, чем просто то, с чем вам приходится иметь дело при использовании фреймворков. Они являются решением невероятно распространенной проблемы: как обрабатывать вызов, который возвращает результат, который может быть в порядке, или может не быть.
Например, возьмите элемент Array.first
. Это удобная утилита, которая дает вам первый элемент массива. Почему полезно иметь возможность называть a.first
, когда вы можете просто позвонить a[0]
? Потому что во время выполнения массив может быть пустым, и в этом случае a[0]
взорвется. Конечно, вы можете проверить a.count
заранее, но затем снова
а. вы можете забыть,
и
б. что приводит к довольно уродливому коду.
Array.first
справляется с этим, возвращая необязательный. Поэтому вам необходимо развернуть необязательный параметр, прежде чем вы сможете использовать значение, являющееся первым элементом массива.
Теперь, к вашей проблеме об развернутом значении, которое существует только внутри блока с помощью if let
. Представьте себе параллельный код, проверяя количество массивов. Это будет одно и то же, верно?
if a.count > 0 {
// use a[0]
}
// outside the block, no guarantee
// a[0] is valid
if let firstElement = a.first {
// use firstElement
}
// outside the block, you _can't_
// use firstElement
Конечно, вы могли бы сделать что-то вроде выполнения раннего возврата из функции, если счетчик равен нулю. Это работает, но немного подвержено ошибкам - что, если вы забыли сделать это или положить его в условное утверждение, которое не выполнялось? По существу, вы можете сделать то же самое с Array.first
: сначала проверьте счетчик функции, а затем выполните array.first!
. Но этот !
как сигнал для вас - будьте осторожны, вы делаете что-то опасное, и вам будет жаль, если ваш код не совсем корректен.
Опционы также помогают сделать альтернативы немного красивее. Предположим, вы хотели установить значение по умолчанию, если массив пуст. Вместо этого:
array.count > 0 ? a[0] : somedefault
вы можете написать это:
array.first ?? somedefault
Это лучше по нескольким причинам. Это ставит важную вещь впереди: значение, которое вы хотите, это то, как начинается выражение, за которым следует значение по умолчанию. В отличие от тернарного выражения, которое сначала показывает вам выражение проверки, а затем значение, которое вы действительно хотите, а затем, наконец, значение по умолчанию. Это также более безопасно - гораздо проще избежать опечатки и невозможно, чтобы эта опечатка привела к взрыву во время работы.
Возьмем другой пример: функция find
. Это проверяет, находится ли значение в коллекции и возвращает индекс его позиции. Но ценность может не присутствовать в коллекции. Другие языки могут справиться с этим, возвращая индекс конца (который не указывает на значение, а скорее минус последнее значение). Это то, что называется "дозорным" значением - значение, которое выглядит как обычный результат, но на самом деле имеет особое значение. Как и в предыдущем примере, вам нужно проверить, что результат не был равен индексу end перед его использованием. Но вы должны это знать. Вы должны найти документы для find
и подтвердить, как это работает.
Если find
возвращает необязательный, это просто естественно, когда вы понимаете необязательную идиому, чтобы понять, что причина в том, что результат может быть недействительным по очевидной причине. И все же о безопасности, упомянутой выше, также применяются - вы случайно не можете забыть и использовать результат в качестве индекса, потому что сначала вам нужно развернуть его.
Тем не менее, вы можете использовать опциональные опции, поскольку они требуют бремени для проверки. Вот почему индексы массива не возвращают необязательные варианты - это создало бы так много хлопот, чтобы постоянно их проверять и разворачивать, особенно если вы знаете, что используемый вами индекс действителен (например, вы находитесь в цикл for над допустимым диапазоном индексов массива), что люди будут постоянно использовать !
и, таким образом, загромождают свой код без выгоды. Но затем вспомогательные методы, такие как первый и последний, добавляются, чтобы охватить распространенные случаи, когда люди хотят быстро выполнить операцию, не проверяя сначала размер массива, но хотите сделать это безопасно.
(Сдвиговые словари, с другой стороны, должны регулярно получать доступ с помощью недопустимых индексов, поэтому их метод [key]
возвращает необязательный)
Еще лучше, если вообще можно избежать возможности выхода из строя. Например, когда filter
не соответствует никаким элементам, он не возвращает nil
необязательный. Он возвращает пустой массив. "Ну, очевидно, это будет", можно сказать. Но вы удивляетесь, как часто вы видите, что кто-то делает возвращаемое значение, например массив, когда на самом деле они просто должны возвращать пустую. Поэтому вы совершенно правильно говорите, что вам следует избегать опций, за исключением случаев, когда они необходимы - это просто вопрос о том, какие необходимые средства. В приведенных выше примерах Id говорят, что они необходимы, и лучшее решение альтернатив.