Вектор Clojure судей

Могут быть случаи, когда использование ! приемлемо, но вы должны использовать его только в том случае, если вы на 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 константа. После кода после защита продолжит выполнение. Если оно не содержит значения - охранник выполнит код в скобках, что приведет к передаче управления, так что код сразу после этого не будет выполнен.

5
задан Kai 24 June 2009 в 17:34
поделиться

2 ответа

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
8
ответ дан 13 December 2019 в 05:41
поделиться

Хорошо, это довольно грубо, но работает:

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>]
4
ответ дан 13 December 2019 в 05:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: