2016-08-05 13 views
7

まず、私は[String]を取得するには、[String?]をマッピングしてみてください。Swift nil-coalescingがオプションで返されるのはなぜですか?

$ xcrun swift 
Welcome to Apple Swift version 2.2 (swiftlang-703.0.18.8 clang-703.0.30). Type :help for assistance. 
    1> import Foundation 
    2> let j: [String?] = ["a", nil] 
j: [String?] = 2 values { 
    [0] = "a" 
    [1] = nil 
} 
    3> j.map {$0 ?? ""} 
$R0: [String] = 2 values { 
    [0] = "a" 
    [1] = "" 
} 

これは私には完璧な意味があります。私はString?とは結びつきません。私はStringになります。しかし[AnyObject?]と、奇妙な何かが起こる:

4> let k: [AnyObject?] = ["a", nil] 
k: [AnyObject?] = 2 values { 
    [0] = "a" 
    [1] = nil 
} 
    5> k.map {$0 ?? ""} 
$R1: [AnyObject?] = 2 values { 
    [0] = "a" 
    [1] = (instance_type = 0x00007fff7bc2c140 @"") 
} 

私はnilに-合体optionalsんだけど、今回は私がオプションを取得します。どうして?

Swift Programming Languagea ?? ba != nil ? a! : bの略記であると言いますが、私はことをしようとしたとき、私は非optionalsの配列を取得します:

6> k.map {$0 != nil ? $0! : ""} 
$R2: [AnyObject] = 2 values { 
    [0] = "a" 
    [1] = "" 
} 

私は??が動作するようになっているか誤解だろうか?ここで何が起こっているのですか?

+2

興味深い質問ですが、これと同じ理由で、これはうまくいきます。let res:[AnyObject] = k.map {$ 0 ?? ""} ' –

+2

' AnyObject'とリテラルで奇妙な型推論問題のように見えます - これもうまくいきます: 'let k1 = k.map {$ 0 ??文字列()} ' – Hamish

答えて

0

これは、2番目と3番目の例では、財団ブリッジの有無にかかわらず無効な構文(ある一方でAppleは、スウィフト3、まだ動作上の第一の例ではスウィフト2のバグ

これを考えられていることを私の注意に来ています)。 Any作品でAnyObject宣言を交換

:ドキュメントが言うようa ?? bはその後、a != nil ? a! : bとまったく同じ動作をします。

2

詳細な動作は十分に文書化されていないため、今後のSwiftでは変更されます。あなたのケースでは

@warn_unused_result 
public func ??<T>(optional: T?, @autoclosure defaultValue:() throws -> T) rethrows -> T 

@warn_unused_result 
public func ??<T>(optional: T?, @autoclosure defaultValue:() throws -> T?) rethrows -> T? 

は、スウィフトは、あなたのコードのために、後者を選択した:

しかし、あなたは演算子を合体知っておくべきことは、2つのオーバーロードがあります。

あなたのような単純化されたコードをテストすることができます。

let x: AnyObject? = "a" 
x ?? "" 

(スウィフト2.2.1で)推論された型がAnyObject?になります。 しかし、このコードも有効です。

let y: AnyObject = x ?? "" 

""のような文字列リテラルは、さまざまな種類として扱うことができます。これらはすべてSwiftで有効です。

"" as String 
"" as String? 
"" as NSString 
"" as NSString? 
"" as AnyObject 
"" as AnyObject? 

ので、いくつかの不特定の理由でスウィフトはAnyObject?を選択しました。 そして、型推論があいまいな場合は、appzYourLifeのコメントに示唆されているように、明示的な型の注釈を使用する必要があります。

+0

興味深い!だから、* Swiftで定義されているようにnil coalescingが定義されているように見えます。つまり、それは特別な構文ではありません。しかし、三項演算子は特別な構文です、そうですか?これは、演算子オーバーロードの型推論ルールが(おそらく意図的に)組込み演算子の推論ルールと異なることを示唆していますか? –

+0

多分私は両方の質問についてはいと言うことができます。既存の '?:'に過負荷をかけようとしても、Swiftに三項演算子を書くことはできません。そして、型推論ルールについては、あなたが見ている通りです。そして、私はこの事実があるべきであることを意味しません。 nil coalescing operatorの使用例を考えてみると、Swiftは非オプションの第一の戦略を使うべきだと私は思う。 – OOPer

関連する問題