Надання значення за замовчуванням для необов’язкового в Swift?


141

Ідіома для роботи з необов'язковими в 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не бути постійною.

Монада Scala's Option (яка в основному така ж ідея, як і Swift's необов'язково) має getOrElseдля цього метод :

val myValue = optionalValue.getOrElse(defaultValue)

Я щось пропускаю? У Swift вже є компактний спосіб зробити це? Або, якщо цього не зробити, чи можна визначити getOrElseв розширенні для необов'язкового?


3
Можливо, пов'язано: чи Swift має оператора
Мартін Р

Відповіді:


289

Оновлення

Зараз 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 myOtional ви можете написати:

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такий самий, як і тип, що міститься в Факультативі. Наразі введіть 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

Не потрібно вказувати Tметод. Це фактично переосмислює існуюче на TФакультативно. Можна просто зробити: func getOrElse(defaultValue: T) -> Tтоді T посилається на тип реального значення необов’язкового, і вам не потрібно вводити його
drewag

Дякую! Я точно це зробив із другої половини вашої відповіді. Чи є спосіб перевірити визначення Факультативного, щоб знати, що родовий тип визначений як Tу цьому? (крім простого припущення на основі конвенції)
Уес

Якщо натиснути команду натиснути Optionalвсередині Xcode, ви побачите, що він визначений якenum Optional<T>
drewag

О, чудово. Я повинен був здогадатися. Визначення там будуть корисними; є багато речей, яких ще немає в документації. Знову дякую.
Уес
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.