力試し:SwiftのOptionalでこれできますか?

  • 42
    いいね
  • 3
    コメント
この記事は最終更新日から1年以上が経過しています。

力試し

Optional は Swift を使う上でとても重要です。 Optional を使いこなせているか試してみて下さい。

Optional を使って次のことをやる場合に、 簡潔かつ安全 に書く方法を考えて下さい。

  1. a: Int? があるとき、 a の値を二乗したい。ただし、 anil の場合は nil を得たい。
  2. array: [Int]? があるとき、 array の最初の要素を取得したい。ただし、 arraynil か、最初の要素が存在しない( Array が空の)場合は nil を得たい。(ヒント: [Int]first: Int? というプロパティを持つ。 first は最初の要素が存在しない場合は nil を返す。)
  3. x: Double? があるとき、 x の平方根を計算したい。ただし、 xnil または負の数の場合は nil を得たい。なお、 sqrt を安全にした(負の数を渡すと nil を返す)関数 safeSqrt: Double -> Double? があるものとして考えて良い。
  4. a: Int?b: Int? があるとき、 a + b を計算したい。ただし、 abnil の場合には nil を得たい。
  5. a: Int? があるとき、 a の値を print で表示したい。ただし、 anil の場合には何も表示したくない。

1, 2, 4 では結果の型が( Int ではなく) Int? に、 3 では Double? になることに注意して下さい。また、 3 の safeSqrt は次のように実装できます。

func safeSqrt(x: Double) -> Double? {
    return x < 0.0 ? nil : sqrt(x)
}

ダメな解答例

簡潔でない例

下記はいずれも正しい結果が得られますが 簡潔ではありません

1.

let result: Int?
if let a0 = a {
    result = a0 * a0
} else {
    result = nil
}

たかが値を二乗するためだけに Optional binding で分岐して計算するなんてやってられません。

2.

let result: Int?
if let array0 = array {
    result = array0.first
} else {
    result = nil
}

3.

let result: Double?
if let x0 = x {
    result = safeSqrt(x0)
} else {
    result = nil
}

4.

let result: Int?
if let a0 = a, b0 = b {
    result = a + b
} else {
    result = nil
}

5.

if let a0 = a {
    print(a0)
}

安全でない例

下記はいずれも正しい結果が得られますが 安全ではありません。また、一見短くて簡潔なように見えますが、 nil チェックと三項演算子、 Forced unwrapping! )の組み合わせは複雑で、簡潔とは言えません。

1.

let result: Int? = a == nil ? nil : a! * a!

せっかく Optional によって安全なコードが書けるようになっているのに、 ! を使ったら台無しです。 nil チェックをしていても : の左右を書き間違えるなどしたら Forced unwrapping に失敗してクラッシュしてしまいます。コードを読む人も ! を見かける度に、この ! はいつも安全なのか、それとも異常系ではクラッシュしてしまうのかを考えなければなりません。

また、わざわざ nil チェックをしなければならないなんて Optional がない時代まで逆戻りしており、 Optional の恩恵を享受できていません。まるで Java で書いているみたいです。

// Java
Integer result = a == null ? null : a * a

2.

let result: Int? = array == nil ? nil : array!.first

3.

let result: Double? = x == nil ? nil : safeSqrt(x!)

4.

let result: Int? = a == nil ? nil : b == nil ? nil : a! + b!

模範解答は・・・

"SwiftのOptional型を極める" で解説しています。この力試しもその一部だったんですが、長くなりすぎたので分離しました。

なお、 2 は簡単ですが出題ミスではありません(話の流れ上必要だったので)。