Предоставляете значение по умолчанию для Optional в Swift?


143

Идиома для работы с опциями в Swift кажется чрезмерно многословной, если все, что вы хотите сделать, это указать значение по умолчанию в случае, если оно равно нулю:

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не требует постоянного значения.

Монада Option в Scala (которая по сути совпадает с идеей необязательной в Swift) имеет getOrElseдля этой цели метод :

val myValue = optionalValue.getOrElse(defaultValue)

Я что-то упускаю? У Swift уже есть компактный способ сделать это? Или, в противном случае, можно ли определить getOrElseрасширение для Optional?


Ответы:


293

Обновить

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на OptionalСвифт.


мой компилятор показывает мне, что тип по- unwrappedValueпрежнему является необязательным типом для этого случая в Swift 1.2: var unwrappedValue = optionalValue ? optionalValue! : defaultValue(xcode 6 beta 4). Это изменилось?
— SimplGy

2
Я ошибаюсь в своей версии. Я на 6.4. Имейте в ??виду: поведение вывода типа по умолчанию заключается в том, что он возвращает необязательный параметр, что обычно не является тем, что вам нужно. Вы можете объявить переменную как необязательную, и это прекрасно работает.
— SimplGy

29

По состоянию на август 2014 года в Swift есть оператор объединения (??), который позволяет это. Например, для необязательного String myOptional вы можете написать:

result = myOptional ?? "n/a"

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


3

Кажется, работает следующее

extension Optional {
    func getOrElse<T>(defaultValue: T) -> T {
        if let value = self? {
            return value as T
        } else {
            return defaultValue
        }
    }
}

однако необходимость в приведении value as T- уродливый прием. В идеале должен быть способ утверждения, который Tсовпадает с типом, содержащимся в Optional. В существующем виде введите наборы для выводаT основаны на параметре, заданном для getOrElse, а затем завершаются ошибкой во время выполнения, если это не соответствует необязательному, а параметр Optional не равен нулю:

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

Указывать Tметод не нужно . Это фактически отменяет существующее Tиз Optional. Вы можете просто сделать: func getOrElse(defaultValue: T) -> Tтогда T относится к типу реального значения необязательного, и вам не нужно вводить его, проверьте его
— drewag

Благодарность! Я сделал вывод из второй половины вашего ответа. Есть ли способ проверить определение Optional, чтобы узнать, что общий тип определен как Tв этом? (помимо простого предположения, основанного на соглашении)
— Wes Campaigne

Если вы щелкните Optionalвнутри Xcode, enum Optional<T>
— удерживая нажатой клавишу Command

Ой, отлично. Я должен был догадаться. Приведенные там определения будут полезны; есть много вещей, которых еще нет в документации. Еще раз спасибо.
— Wes Campaigne
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.