Podanie wartości domyślnej opcjonalnego w języku Swift?


141

Idiom do radzenia sobie z opcjami w Swift wydaje się nadmiernie rozwlekły, jeśli wszystko, co chcesz zrobić, to podać wartość domyślną w przypadku, gdy jest zerowa:

if let value = optionalValue {
    // do something with 'value'
} else {
    // do the same thing with your default value
}

co wiąże się z niepotrzebnym powielaniem kodu lub

var unwrappedValue
if let value = optionalValue {
    unwrappedValue = value
} else {
    unwrappedValue = defaultValue
}

która unwrappedValuenie wymaga stałej.

Monada Option Scali (która jest w zasadzie tym samym pomysłem co opcja Swift) ma metodę getOrElsedo tego celu:

val myValue = optionalValue.getOrElse(defaultValue)

Czy coś mi brakuje? Czy Swift ma już na to kompaktowy sposób? Lub, jeśli to nie wystarczy, czy można zdefiniować getOrElserozszerzenie dla Optional?


Odpowiedzi:


289

Aktualizacja

Firma Apple dodała teraz operatora koalescencji:

var unwrappedValue = optionalValue ?? defaultValue

Operator trójskładnikowy jest w tym przypadku Twoim przyjacielem

var unwrappedValue = optionalValue ? optionalValue! : defaultValue

Możesz także podać własne rozszerzenie opcjonalnego wyliczenia:

extension Optional {
    func or(defaultValue: T) -> T {
        switch(self) {
            case .None:
                return defaultValue
            case .Some(let value):
                return value
        }
    }
}

Następnie możesz po prostu zrobić:

optionalValue.or(defaultValue)

Zalecam jednak trzymać się operatora trójskładnikowego, ponieważ inni programiści zrozumieją to znacznie szybciej bez konieczności badania ormetody

Uwaga : Zacząłem moduł dodawania wspólne pomocników tak orna OptionalSWIFT.


mój współpracownik pokazuje mi, że typ unwrappedValuejest nadal opcjonalnym typem dla tego przypadku w Swift 1.2: var unwrappedValue = optionalValue ? optionalValue! : defaultValue(xcode 6 beta 4). Czy to się zmieniło?
— SimplGy

2
Mylę się co do mojej wersji. Jestem na 6.4. Uważaj: ??domyślne zachowanie wnioskowania o typie polega na tym, że zwraca opcjonalne, co zwykle nie jest tym, czego chcesz. Możesz zadeklarować zmienną jako nieobowiązkową i to działa dobrze.
— SimplGy

29

Od sierpnia 2014 r. Swift ma operatora koalescencji (??), który to umożliwia. Na przykład dla opcjonalnego String myOptional można napisać:

result = myOptional ?? "n/a"

4

jeśli napisałeś:

let result = optionalValue ?? 50

a optionalValue != nilpotem też resultbędzie optionali będziesz musiał go rozpakować w przyszłości

Ale możesz napisać operator

infix operator ??? { associativity left precedence 140 }

func ???<T>(optLeft:T?, right:T!) -> T!
{
    if let left = optLeft
    {
        return left
    }
    else { return right}
}

Teraz możesz:

 let result = optionalValue ??? 50

A kiedy optionalValue != nilto resultbędzieunwraped


3

Następujące wydaje się działać

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

jednak potrzeba rzucania value as Tjest brzydka. W idealnym przypadku powinien istnieć sposób potwierdzenia, że Tjest taki sam, jak typ zawarty w pliku Optional. W obecnej postaci wpisz zestawy wnioskowania Tna podstawie parametru podanego w getOrElse, a następnie zakończy się niepowodzeniem w czasie wykonywania, jeśli nie jest to zgodne z wartością opcjonalną, a wartość opcjonalna jest różna od zera:

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

Nie musisz określać Tmetody. To faktycznie zastępuje istniejące Tz Optional. Możesz po prostu zrobić: func getOrElse(defaultValue: T) -> Twtedy T odnosi się do rzeczywistego typu wartości opcjonalnej i nie musisz wpisywać, sprawdź to
— drewag

Dzięki! Dokładnie to wywnioskowałem z drugiej połowy twojej odpowiedzi. Czy jest jakiś sposób, aby sprawdzić definicję Opcjonalny, aby wiedzieć, że typ ogólny jest zdefiniowany Tw ten sposób? (poza prostym założeniem opartym na konwencji)
— Wes Campaigne

Jeśli klikniesz polecenie Optionalwewnątrz Xcode, zobaczysz, że jest zdefiniowany jakoenum Optional<T>
— drewag,

Och, świetnie. Powinienem się domyślić. Definicje tam zawarte będą przydatne; jest wiele rzeczy, których nie ma jeszcze w dokumentacji. Dzięki jeszcze raz.
— Wes Campaigne
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.