質問: ドキュメント全般の見方、ということになるのですが、具体例として、 https://developer.apple.com/documentation/swift/optional 上記のページのNil結合演算子(Coalescing Nil Values)の部分に、 > > Coalescing Nil Values > > > func ?? (T?, () -> T) -> T > > Performs a nil-coalescing operation, returning the wrapped value of an Optional instance or a default value. > > > func ?? (T?, () -> T?) -> T? > > Performs a nil-coalescing operation, returning the wrapped value of an Optional instance or a default Optional value. > > > とあるのですが、二番目の引数「() -> T」と「() -> T?」は何を表しているのでしょうか。 現在の私の認識だと、引数無し・戻り値の型がT,T?であるクロージャの型を示しているのかな、という感じなんですが、 なぜクロージャが出てくるんでしょうか? nil結合演算子の挙動については一応理解したつもりです。 が型引数、多分一番目の引数が左辺、二番目の引数が右辺ということでしょうか。 例えば左辺がInt?型の場合、右辺はInt型のデフォルト値を指定して、 左辺が値を保持している場合は、アンラップして取り出したその値を返す、 左辺がnilの場合はデフォルト値として指定した右辺の値を返す、 というのがnil結合演算子、 以上が現在の私の認識です。
回答: 第一引数は左辺、第二引数は右辺というのはあっています。 についての考え方も正しいです。 では第二引数の型ですが、その先の説明ページを見てください ``` func ?? (optional: T?, defaultValue: @autoclosure () throws -> T) rethrows -> T ``` となっています。 throws, rethrowsは例外機構の話ですので今回は無視しましょう。 第二引数は`() -> T`ですがその前に`@autoclosure`というのが付いているのがミソです。 `@autoclosure`が付いているとその型の値を渡すと自動的にクロージャに包まれるようにコンパイルされます。 ``` let a = optionalInt ?? 0 ``` はコンパイル時に ``` let a = optionalInt ?? { 0 } ``` のようにふるまうようになります。 これの何が便利なのかというと、例えばnilなら何かしてその値を使うという場合、つまり ``` let a = optionalInt ?? getDefaultIntValue() ``` このような場合です。 swiftの演算子の実体は関数ですので`??`を呼び出す**前**に`getDefaultIntValue()`を呼び出しその結果を`??`に与えることになってしまいます。 ですが通常`optionalInt`がnilの時のみ実行される方がよい場合はほとんどです。 `@autoclosure`が付いていれば第二引数は`{ getDefaultIntValue() }`となり、`??`を呼び出す前に`getDefaultIntValue()`を呼び出す必要がなくなります。 処理の流れを分かりやすく`??`の実装を書いてみると ``` func ?? (optional: T?, defaultValue: @autoclosure () throws -> T) rethrows -> T { if optional != nil { return optional! } return defaultValue() /// ここではじめてクロージャが実行される。 } ``` のようになります。 クロージャは左辺がnilの時にしか実行されません。 つまり先の例の`getDefaultIntValue()`も左辺がnilの時にしか実行されないということです。