2016-08-05 4 views
7

पहले, मैं एक [String?] मानचित्रण का प्रयास करें, प्राप्त करने के लिए:स्विफ्ट नील-कोलेसिंग वैकल्पिक विकल्प क्यों लौट रहा है? एक <code>[String]</code>

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

यह मेरे लिए एकदम सही समझ में आता है। मैं nil-coalesce 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 @"") 
} 

मैं शून्य-वालों optionals हूँ, लेकिन इस बार मैं एक वैकल्पिक बाहर निकलना। क्यूं कर?

Swift Programming Language कहते a ?? ba != nil ? a! : b के लिए आशुलिपि है, लेकिन जब मैं कि कोशिश, मैं गैर optionals की एक सरणी बाहर निकलना:

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

मैं गलत समझ रहा हूँ कैसे ?? काम करने के लिए माना जाता है? यहाँ क्या हो रहा है?

+2

दिलचस्प सवाल, इसी कारण से यह काम करने लगता है 'res res: [AnyObject] = k.map {$ 0 ?? ""} ' –

+2

'एनीऑब्जेक्ट' और शाब्दिक के साथ एक अजीब प्रकार अनुमान समस्या जैसा दिखता है - यह भी काम करता है: 'k1 = k.map {$ 0 ?? स्ट्रिंग()} ' – Hamish

उत्तर

0

यह मेरा ध्यान में आया है कि एप्पल इस स्विफ्ट में एक बग 2.

स्विफ्ट 3 में, ऊपर 1 उदाहरण अभी भी काम करता है, जबकि 2 और 3 उदाहरण अवैध वाक्य रचना कर रहे हैं (के साथ या फाउंडेशन ब्रिजिंग बिना विचार)।

Any काम करता है के साथ AnyObject घोषणा की जगह: a ?? b तो, a != nil ? a! : b के समान व्यवहार करता है प्रलेखन कहते हैं।

2

विस्तृत व्यवहार अच्छी तरह से प्रलेखित नहीं है, इसलिए भविष्य में स्विफ्ट में बदल जाएगा।

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

आपके मामले में, स्विफ्ट अपने कोड के लिए बाद चुना गया है:

लेकिन आप ऑपरेटर वालों को पता होना चाहिए दो भार के है।

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

अनुमानित प्रकार (स्विफ्ट 2.2.1 में) AnyObject? हो जाता है:

आप की तरह एक सरल कोड के साथ परीक्षण कर सकते हैं। लेकिन यह कोड भी मान्य है।

"" तरह
let y: AnyObject = x ?? "" 

स्ट्रिंग शाब्दिक विभिन्न प्रकारों की संख्या के रूप में इलाज किया जा सकता। ये सभी स्विफ्ट में मान्य हैं।

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

तो, कुछ अनिर्दिष्ट कारण के साथ स्विफ्ट AnyObject? चुना है। और, यदि प्रकार की अनुमान अस्पष्ट हो सकती है, तो आपको स्पष्ट प्रकार की एनोटेशन का उपयोग करना चाहिए, जैसा कि ऐपज़ोर लाइफ की टिप्पणी में सुझाया गया है।

+0

दिलचस्प! तो ऐसा लगता है जैसे नील कोलेसिंग * स्विफ्ट में परिभाषित किया गया है, यानी, यह सिर्फ विशेष वाक्यविन्यास नहीं है। लेकिन टर्नरी ऑपरेटर विशेष वाक्यविन्यास है, है ना? क्या यह सुझाव देता है कि ऑपरेटर ओवरलोड के लिए टाइप अनुमान नियम (शायद अनजाने में) अंतर्निहित ऑपरेटरों के लिए अलग हैं? –

+0

शायद मैं दोनों प्रश्नों के लिए हाँ कह सकता हूं। आप स्विफ्ट में किसी भी टर्नरी ऑपरेटरों को नहीं लिख सकते हैं, भले ही आप मौजूदा '?: 'को अधिभारित करने का प्रयास करें। और प्रकार के अनुमान नियमों के बारे में, तथ्य यह है कि आप देखते हैं। और मेरा मतलब यह नहीं है कि यह तथ्य यह होना चाहिए। नील कोलेसिंग ऑपरेटर के उपयोग के मामलों को ध्यान में रखते हुए, स्विफ्ट को गैर-वैकल्पिक पहली रणनीति का उपयोग करना चाहिए, मुझे लगता है। – OOPer

संबंधित मुद्दे