Swiftのオプションのデフォルト値を提供していますか?


141

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のOptionモナド(基本的にはSwiftのOptionalと同じ考え方です)には、getOrElseこの目的のためのメソッドがあります。

val myValue = optionalValue.getOrElse(defaultValue)

何か不足していますか?Swiftにはすでにコンパクトな方法がありますか?または、それが失敗した場合、getOrElseオプションの拡張で定義することは可能ですか?


3
関連する可能性があります
Martin R

回答:


289

更新

アップルは今合体演算子を追加しました:

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メソッドを調査する必要なく、より迅速にそれを理解するため、3項演算子を使用することをお勧めします。

:私は始めたモジュールをこのような一般的なヘルパーを追加することorOptional迅速に。


私のコンパイラはunwrappedValue、Swift 1.2では、このタイプのタイプがまだオプションのタイプであることを示しています。var unwrappedValue = optionalValue ? optionalValue! : defaultValue(xcode 6 beta 4)。これは変わりましたか?
SimplGy 2015

2
私のバージョンは間違っています。6.4です。注意してください:??デフォルトの型推論の振る舞いは、それがオプションを返すことです。変数を非オプションとして宣言でき、これはうまく機能します。
SimplGy 2015

29

2014年8月現在、Swiftにはそれを可能にする合体演算子(??)があります。たとえば、オプションの文字列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 != nilresultなる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に指定されたパラメーターに基づいて型推論セットを実行し、これがオプションと一致せず、オプションが非nilの場合、実行時に失敗します。

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メソッドを指定する必要はありません。これは、既存のTOptionalを実際にオーバーライドします。ただ行うことができますfunc getOrElse(defaultValue: T) -> T。Tはオプションの実際の値タイプを参照し、それをチェックする必要はありません
drewag

ありがとう!私はあなたの応答の後半からそれを正確に推測しました。ジェネリック型がTそのように定義されていることを知るためにOptionalの定義を検査する方法はありますか?(慣例に基づいて単純に仮定することを超えて)
Wes Campaigne

OptionalXcode内でコマンドクリックすると、次のように定義されていることがわかりますenum Optional<T>
drewag

ああ、すばらしい。私は推測したはずです。そこにある定義が役に立つでしょう。ドキュメントにはまだ含まれていないことがたくさんあります。再度、感謝します。
Wes Campaigne
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.