Надання значення за замовчуванням для необов’язкового в 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.