Предоставление значения по умолчанию для параметра Опция в Swift? - программирование
Подтвердить что ты не робот

Предоставление значения по умолчанию для параметра Опция в 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 в расширении для необязательного?

4b9b3361

Ответ 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)

Вы можете просмотреть этот репозиторий.