2015-11-25 14 views
9

टीएल; डीआर

यह क्यों काम नहीं करता है?मानचित्र में init() का उपयोग()

"abcdefg".characters.map(String.init) // error: type of expression is ambiguous without more context 

विवरण

एक वास्तव में अच्छी बात यह है कि मैं स्विफ्ट में अपना पसंदीदा init विधि में पारित करके दूसरे करने के लिए एक बात का एक संग्रह को परिवर्तित करने की क्षमता है (के लिए उस प्रकार से मौजूद एक init() कल्पना करते हुए)।

यहां एक उदाहरण है जो ट्यूपल्स की सूची को ClosedInterval के उदाहरणों में परिवर्तित कर रहा है।

[(1,3), (3,4), (4,5)].map(ClosedInterval.init) 

उदाहरण भी सच है कि हम जब तक टपल के रूप में समारोह के तर्क सूची से मिलान एक भी तर्क के रूप में तर्कों की किसी टपल पारित कर सकते हैं का लाभ लेता है।

यहां एक और उदाहरण, इस बार संख्याओं की सूची स्ट्रिंग उदाहरणों में परिवर्तित कर रहा है।

(1...100).map(String.init) 

दुर्भाग्य से, अगला उदाहरण काम नहीं करता है। यहां मैं एक स्ट्रिंग को सिंगल-कैरेक्टर स्ट्रिंग्स की सूची में विभाजित करने की कोशिश कर रहा हूं।

"abcdefg".characters.map(String.init) // error: type of expression is ambiguous without more context 

map()Character की एक सूची पर काम किया जाना चाहिए (और वास्तव में मैं एक खेल का मैदान है कि स्विफ्ट [चरित्र] का सही प्रकार यहाँ map में पारित किया जा रहा infers में सत्यापित करने में सक्षम था)।

String निश्चित रूप से Character से तुरंत चालू किया जा सकता है।

let a: Character = "a" 
String(a) // this works 

और दिलचस्प बात यह है कि यह काम करता है यदि पात्र प्रत्येक अपनी सरणी में हैं।

"abcdefg".characters.map { [$0] }.map(String.init) 

या समकक्ष:

let cx2: [[Character]] = [["a"], ["b"], ["c"], ["d"]] 
cx2.map(String.init) 

मैं जानता हूँ कि मैं यह कर सकता है कि:

"abcdefg".characters.map { String($0) } 

लेकिन मैं विशेष रूप से समझने के लिए क्यों "abcdefg".characters.map(String.init) काम नहीं करता है कोशिश कर रहा हूँ (IMO इस वाक्य रचना है और भी पठनीय और सुरुचिपूर्ण)

उत्तर

13

सरलीकृत रेपो:

String.init as Character -> String 
// error: type of expression is ambiguous without more context 

इसका कारण यह है String दो initializers कि एक Character स्वीकार किया है:

init(_ c: Character) 
init(stringInterpolationSegment expr: Character) 

जहाँ तक मुझे पता है, वहाँ जब एक मूल्य के रूप में प्रारंभकर्ता का उपयोग कर उन्हें स्पष्ट करने के लिए कोई रास्ता नहीं है।

(1...100).map(String.init) के लिए, String.init को Int -> String के रूप में जाना जाता है।हालांकि दोनों initializers कि एक Int स्वीकार देखते हैं:

init(stringInterpolationSegment expr: Int) 
init<T : _SignedIntegerType>(_ v: T) 

जेनेरिक प्रकार कमजोर स्पष्ट प्रकार से है। तो संकलक इस मामले में stringInterpolationSegment: एक चुनते हैं। आप पुष्टि कर सकते हैं कि कमांड + .init पर क्लिक करें।

+1

यह एक उत्कृष्ट उत्तर है। क्या कोई संदर्भ दस्तावेज़ (या यहां तक ​​कि एक लेख) है जो इस तरह से '.init' का उपयोग करने का वर्णन करता है (उदा। मानचित्र/flatMap, आदि में)? –

+1

आप दो शुरुआती लोगों को असंबद्ध कर सकते हैं; पहले को संदर्भित करने के लिए 'String.init (_ :)' का उपयोग करें। – Sweeper

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