Могут быть случаи, когда использование !
приемлемо, но вы должны использовать его только в том случае, если вы на 100% уверены, что необязательный параметр содержит значение.
Хотя может быть случай, когда вы можете использовать принудительное развертывание, как вы знаете для факта , что опциональный элемент содержит значение - нет одиночного место, где вы не можете безопасно развернуть эту опцию вместо этого.
Эти переменные разработаны таким образом, что вы можете отложить их назначение на более поздний срок в своем коде. Это ваша ответственность за обеспечение их ценности, прежде чем вы получите к ним доступ. Однако, поскольку они включают в себя принудительное развертывание, они по-прежнему небезопасны - поскольку они предполагают , что ваше значение не равно нулю, даже если присвоение nil допустимо.
Вы должны использовать неявно развернутые опции только как последнее средство . Если вы можете использовать ленивую переменную или предоставить для переменной значение по умолчанию - вы должны сделать это вместо использования неявно развернутого необязательного параметра.
Однако, есть несколько сценариев, в которых неявно развернутые необязательные опции являются полезными , и вы все еще можете использовать различные способы их безопасного развертывания, как указано ниже - но вы должны всегда используйте их с осторожностью.
Самый простой способ проверить, содержит ли опциональное значение значение, - сравнить его с nil
.
if anOptionalInt != nil {
print("Contains a value!")
} else {
print("Doesn’t contain a value.")
}
Тем не менее, в 99,9% случаев при работе с опциями вы действительно захотите получить доступ к содержащемуся в нем значению, если оно вообще есть. Для этого вы можете использовать Дополнительное связывание .
Необязательное связывание позволяет проверить, содержит ли необязательное значение значение, и позволяет назначить развернутое значение новой переменной или константе. Он использует синтаксис if let x = anOptional {...}
или if var x = anOptional {...}
, в зависимости от того, нужно ли вам изменить значение новой переменной после ее привязки.
Например:
if let number = anOptionalInt {
print("Contains a value! It is \(number)!")
} else {
print("Doesn’t contain a number")
}
Сначала необходимо проверить, что необязательный параметр содержит значение. Если он делает , то значение «unwrapped» присваивается новой переменной (number
), которую вы можете затем свободно использовать, как если бы она была необязательной. Если необязательный не содержит значение, то будет вызываться предложение else, как и следовало ожидать.
Что хорошего в дополнительном связывании, так это в том, что вы можете развернуть несколько дополнительных компонентов одновременно. Вы можете просто отделить утверждения запятой. Оператор будет успешным, если все дополнительные параметры были развернуты.
var anOptionalInt : Int?
var anOptionalString : String?
if let number = anOptionalInt, let text = anOptionalString {
print("anOptionalInt contains a value: \(number). And so does anOptionalString, it’s: \(text)")
} else {
print("One or more of the optionals don’t contain a value")
}
Еще одна хитрость заключается в том, что вы можете также использовать запятые, чтобы проверять определенное условие для значения после его разворачивания.
if let number = anOptionalInt, number > 0 {
print("anOptionalInt contains a value: \(number), and it’s greater than zero!")
}
Единственный недостаток использования необязательного связывания в операторе if состоит в том, что вы можете получить доступ только к развернутому значению изнутри области действия оператора. Если вам нужен доступ к значению вне области действия оператора, вы можете использовать защитный оператор .
Защитное заявление позволяет вам определить условие успеха - и текущая область будет продолжать выполняться, только если это условие выполнено. Они определены с помощью синтаксиса guard condition else {...}
.
Итак, чтобы использовать их с необязательной привязкой, вы можете сделать это:
guard let number = anOptionalInt else {
return
}
(Обратите внимание, что в теле охранника вы должны использовать один из операторы управления передачей для выхода из области текущего выполняемого кода). Sup>
Если anOptionalInt
содержит значение, оно будет развернуто и назначено новому number
константа. После кода после защита продолжит выполнение. Если оно не содержит значения - охранник выполнит код в скобках, что приведет к передаче управления, так что код сразу после этого не будет выполнен.
user> (doc repeatedly)
-------------------------
clojure.core/repeatedly
([f])
Takes a function of no args, presumably with side effects, and returns an infinite
lazy sequence of calls to it
nil
user> (take 5 (repeatedly #(ref nil)))
(#<Ref@1f10a67: nil> #<Ref@1e2161d: nil> #<Ref@1a034d: nil> #<Ref@1cee792: nil> #<Ref@c5577c: nil>)
us
Хорошо, это довольно грубо, но работает:
user=> (map (fn [_] (ref nil)) (range 5))
(#<Ref@27147d: nil> #<Ref@b248c8: nil> #<Ref@c86116: nil> #<Ref@5e06ef: nil> #<Ref@19719f: nil>)
Это возвращает LazySeq, поэтому, если вам нужен / нужен вектор, просто используйте:
user=> (vec (map (fn [_] (ref nil)) (range 5)))
[#<Ref@5bf9cf: nil> #<Ref@6dbfb0: nil> #<Ref@43f787: nil> #<Ref@2fe9bf: nil> #<Ref@9b1e15: nil>]