LoginSignup
0
0

More than 5 years have passed since last update.

多重unwrap

Posted at

a: A?? を要領よくアンラップしたい

let a: A??

if let z = a ?? nil {}

元ネタ:

@cocoaphony let w: UIWindow? = app.delgate?.window?? nil
That is my approach for double optionals in 1.2. (trailing ? works in 1.1.)

解説

シンタックスシュガー ??? があるとわかりにくいので外す
それぞれの定義は以下

// ? (Optional)
// https://github.com/apple/swift/blob/7ed7354003406c8e4a708195b86c1950b2c1f381/stdlib/public/core/Optional.swift#L122-L133
enum Optional<T> {
  case none
  case some(t: T)
}

// ?? (Nil-Coalescing Operator)
// https://github.com/apple/swift/blob/7ed7354003406c8e4a708195b86c1950b2c1f381/stdlib/public/core/Optional.swift#L655-L663
public func ?? <T>(optional: T?, defaultValue: @autoclosure () throws -> T)
    rethrows -> T {
  switch optional {
  case .some(let value):
    return value
  case .none:
    return try defaultValue()
  }
}

処理の中身を見ていく

// 以下の二行は同義
let a: A??
let a: Optional<Optional<A>>

// この文を分解していく 
if let z = a ?? nil {}  

// ?? と if-let に分離
let b = a ?? nil  // ①
if let z = b {}     // ②

// ①から見ていく
// a は Optional<Optional<A>> であるので、?? (Nil-Coalescing Operator) のジェネリック型 T は Optional がひとつ外れた Optional<A> である
// ということは右辺の nil は Optional<A>.none であることがわかる
// つまり b は Optional<A> である
let b: Optional<A> = a ?? nil

// あとは②に入れるだけ
if let b = z {}  // z: A?
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0