Предоставление значения по умолчанию для параметра Опция в Swift?
Идиома для работы с опциями в Swift кажется чрезмерно многословной, если все, что вы хотите сделать, это предоставить значение по умолчанию в случае, когда оно равно nil:
if let value = optionalValue {
// do something with 'value'
} else {
// do the same thing with your default value
}
который включает ненужный дублирующий код, или
var unwrappedValue
if let value = optionalValue {
unwrappedValue = value
} else {
unwrappedValue = defaultValue
}
для которого unwrappedValue
не является константой.
Scala Вариант monad (который в основном представляет ту же идею, что и Swift Необязательно) имеет для этого метод getOrElse
:
val myValue = optionalValue.getOrElse(defaultValue)
Я что-то упустил? У Swift есть компактный способ сделать это уже? Или, если это невозможно, можно ли определить getOrElse
в расширении для необязательного?
Ответы
Ответ 1
Обновление
В Apple теперь добавлен коалесцирующий оператор:
var unwrappedValue = optionalValue ?? defaultValue
В этом случае тройной оператор - ваш друг
var unwrappedValue = optionalValue ? optionalValue! : defaultValue
Вы также можете указать собственное расширение для необязательного перечисления:
extension Optional {
func or(defaultValue: T) -> T {
switch(self) {
case .None:
return defaultValue
case .Some(let value):
return value
}
}
}
Тогда вы можете просто сделать:
optionalValue.or(defaultValue)
Однако я рекомендую придерживаться тернарного оператора, так как другие разработчики поймут это гораздо быстрее, не изучая метод or
Примечание: я начал использовать модуль, чтобы быстро добавить общих помощников, таких как or
on Optional
.
Ответ 2
По состоянию на август 2014 года Swift имеет коалесцирующий оператор (??), который позволяет это. Например, для необязательного String myOptional вы можете написать:
result = myOptional ?? "n/a"
Ответ 3
Кажется, что работает
extension Optional {
func getOrElse<T>(defaultValue: T) -> T {
if let value = self? {
return value as T
} else {
return defaultValue
}
}
}
однако необходимость бросать value as T
является уродливым взломом. В идеале должен быть способ утверждать, что T
совпадает с типом, содержащимся в опции. Как бы то ни было, наберите наборы T
на основе параметра, заданного для getOrElse, а затем выйдите из строя во время выполнения, если это не соответствует опции "Дополнительно" и "Необязательно" не является ником:
let x: Int?
let y = x.getOrElse(1.414) // y inferred as Double, assigned 1.414
let a: Int? = 5
let b: Double = a.getOrElse(3.14) // Runtime failure casting 5 to Double
Ответ 4
если вы написали:
let result = optionalValue ?? 50
и optionalValue != nil
, тогда result
тоже будет optional
, и вам понадобится развернуть его в будущем
Но вы можете написать оператор
infix operator ??? { associativity left precedence 140 }
func ???<T>(optLeft:T?, right:T!) -> T!
{
if let left = optLeft
{
return left
}
else { return right}
}
Теперь вы можете:
let result = optionalValue ??? 50
И когда optionalValue != nil
, тогда result
будет unwraped
Ответ 5
Я создал простую библиотеку расширений и сам использовал ее для сокращения таких повторяющихся кодов. Он отбрасывает и возвращает необязательные примитивные типы в значение по умолчанию. Вы просто бросаете его, как показано ниже,
CGFloat(optionalValue)
или с определенным значением по умолчанию,
Int(optionalValue, defaultValue: 100)
Вы можете просмотреть этот репозиторий.