2016-08-05 24 views
7

Birincisi, almak, bir [String?] haritalama deneyin bir [String]:Neden Swift nil-birleştirmeyi isteğe bağlı olarak döndürüyor?

$ 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] = "" 
} 

Bu benim için çok mantıklı. Ben String? nolu birleştirme ve String aldım. Ama [AnyObject?] ile, garip bir şey olur:

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 @"") 
} 

ben nil-kaynaştırma isteğe bağlı öğeleri değilim, ama bu kez isteğe bağlı çıkmak. Niye ya?

Swift Programming Languagea ?? ba != nil ? a! : b için kısaltmadır diyor, ama ben çalıştığınızda, ben olmayan seçeneklere bir dizi çıkmak: İşe gerekiyordu nasıl ??

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

yanlış anlama ben? Burada neler oluyor?

+2

İlginç bir soru, aynı nedenden dolayı bu işe yaramıyor gibi görünüyor: res: [AnyObject] = k.map {$ 0 ?? ""} " –

+2

" AnyObject "ve literals ile garip bir tür çıkarsama sorunu gibi görünüyor - bu da çalışır:' k1 = k.map {$ 0 ?? String()} ' – Hamish

cevap

0

Apple bu

Swift 3, yukarıdaki 1 örnek hâlâ çalışmaktadır, 2. ve 3. örnekler ile veya Vakıf Köprüsüzlük (geçersiz sözdizimi ise 2. Swift bir hata olarak gördüğünü benim dikkatimizi çekmiştir).

Any eserlerle AnyObject beyanı Değiştirme: dokümantasyon söylediği gibi a ?? b sonra, a != nil ? a! : b gibi davranır.

2

Detaylı davranış iyi belgelenmiş değildir, bu nedenle, gelecekte Swift'ler değişecektir. Senin durumunda

@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? 

, Swift kodunuz için ikincisi seçti:

Ama operatörü kaynaştırma bilmelidir iki aşırı yüklenmeleri vardır. (Swift 2.2.1 olarak) AnyObject? olur

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

türetilmiş tip:

Sen gibi basitleştirilmiş kodları ile test edebilirsiniz. Ancak bu kod da geçerlidir. "" gibi

let y: AnyObject = x ?? "" 

dize hazır türleri ve çeşitli şekilde tedavi edilebilir. Bunların hepsi Swift'de geçerlidir.

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

Yani, bazı belirtilmemiş sebeple Swift AnyObject? seçmiştir. Ve, tür çıkarımının belirsiz olması durumunda, appzYourLife'ın yorumunda önerildiği gibi açık tip ek açıklama kullanmalısınız.

+0

İlginç! Yani, nil birleştirme * tanımlanır. * Swift, yani sadece özel bir sözdizimi değildir. Ama üçlü operatör özel sözdizimi, değil mi? Bu, operatör aşırı yükleri için tür çıkarım kurallarının (belki de istemeden) yerleşik operatörlerinkinden farklı olduğunu gösteriyor mu? –

+0

Belki de her iki soru için de evet diyebilirim. Var olan 'aşırı yüklenmeye çalışsanız bile Swift'de herhangi bir üçlü işleç yazamazsınız. Ve tür çıkarım kuralları hakkında, aslında gördüğünüz gibi. Ve bu gerçek olması gerektiği anlamına gelmez. Nil birleştirme operatörünün kullanım durumları göz önünde bulundurulduğunda, Swift'in seçmeli olmayan ilk stratejiyi kullanması gerektiğini düşünüyorum. – OOPer

İlgili konular