2015-11-23 9 views
7

सामान्य शीर्षक के लिए खेद है, उदाहरण के बिना समस्या का वर्णन करना मुश्किल है।इस सामान्य कार्य के साथ क्या चल रहा है?

func test<T: Equatable>(expect expected: T, run:() -> T) { 
    let value = run() 
    if value == expected { 
     print("OK") 
    } else { 
     print("Expected: \(expected), Actual: \(value)") 
    } 
} 

यहाँ कहा फ़ंक्शन का उपयोग का एक उदाहरण है:

मान लीजिए मैं निम्नलिखित सामान्य समारोह है कि Equatable प्रकार के लिए विवश है परिभाषित

test(expect: 100) { 10 * 10 } // prints "OK" 
test(expect: 1000) { 10 * 10 } // prints "Expected: 1000, Actual: 100" 

और, बेशक, मैं स्टोर कर सकते हैं अक्षर का उपयोग करने के बजाय मूल्य:

let e = 100 
test(expect: e) { e } // prints "OK" 

अब तक इतना अच्छा है, सबकुछ अपेक्षित काम करता है (कोई इरादा नहीं है)।

अब चलो एक सरणी के साथ इस की कोशिश करते हैं:

test(expect: [1, 2]) { [1, 2] } // prints "OK" 

एक बार फिर, चीजों को बाहर काम करते हैं।

लेकिन अब हम इस प्रयास करें:

let a = [1, 2] 
test(expect: a) { a } // error: cannot convert value of type '() -> [Int]' to expected argument type '() -> _' 

तो सवाल मैं कर रहा करने के लिए का निर्माण किया है: यह काम क्यों नहीं करता है?

खेल का मैदान सही ढंग से लाने का प्रयास a के प्रकार [Int] है, इसलिए जहां () -> _ की उम्मीद से आता है?

पिछले उदाहरण के रूपांतरों का एक समूह की कोशिश कर रहा:

test(expect: a) { return a } 
test(expect: a) { return a as [Int] } 
test(expect: a as [Int]) { return a as [Int] } 
test(expect: [1, 2]) { a } 
test(expect: [1, 2] as [Int]) { a } 

वे एक ही समस्या में सभी परिणाम। किसी कारण से, स्विफ्ट को लगता है कि समारोह () -> _ की अपेक्षा करता है।

तो शायद यह सिर्फ इसलिए सरणियों नहीं Equatable हैं, लेकिन यह काम करता है:

let a = [1, 2] 
[1, 2] == [1, 2] 
a == a 

मैंने सोचा कि मैं जेनरिक समझा बहुत अच्छी तरह से है, और मैं पूरी तरह से इस से स्टम्प्ड रहा हूँ। क्या यह test() की मेरी परिभाषा में स्विफ्ट या बग में एक बग है? क्या लक्ष्य भी पूरा किया जा सकता है?

समाधान

@ नीचे Sulthan का जवाब, मैं इस समारोह सरणी मामले को संभालने के लिए का एक और संस्करण (और उस बात के लिए किसी भी SequenceType) लिखने में सक्षम था

धन्यवाद:

public func test<T: SequenceType where T.Generator.Element: Equatable>(expect expected: T, run:() -> T) { 
    let result = run() 
    // Note: zip() will stop at the shorter array, so this implementation isn't correct, don't use it (it will incorrectly end up saying [1] == [1,2]). This code is just here to demonstrate the function's generic constraint. 
    let eq = zip(expected, result).filter(!=).isEmpty 
    if eq { 
     print("OK") 
    } else { 
     print("Expected: \(expected), Actual: \(result)") 
    } 
} 

let a: [Int] = [1, 2] 
test(expect: [1,2]) { a } // prints "OK" 
test(expect: [1,3]) { a } // prints "Expected: [1, 3], Actual: [1, 2]" 
+2

उत्तर http://stackoverflow.com/a/33732669/669586 के समान है, लेकिन मुझे यकीन नहीं है कि मुझे इसे डुप्लिकेट के रूप में बंद करना चाहिए या नहीं। – Sulthan

+1

यह @Sulthan निश्चित रूप से इसकी जड़ में एक ही सवाल है, लेकिन तथ्य यह है कि एक समारोह के माध्यम से यह कर समस्या एक सा मुझे लगता है कि यह अपने आप ही खड़े करने के लिए योग्य बनाता है obfuscates है। इसके अलावा, सवाल का हिस्सा यह था कि इस काम को कैसे बनाया जाए, जो प्रश्न के संपादन को भी संबोधित करता है। – vopilif

+0

उपरोक्त मेरे "समाधान" के बारे में एक साइड नोट के रूप में। 'Test()' के कार्यान्वयन को 'अनुक्रम प्रकार' में कार्यान्वित करना शायद एक बुरा विचार है क्योंकि यह अनंत अनुक्रमों के लिए मान्य है, इसलिए आप उन सभी पर पुन: प्रयास करने की कोशिश नहीं करना चाहते हैं। 'कलेक्शन टाइप' अधिक उपयुक्त होगा। – vopilif

उत्तर

5

सरणी डॉन स्वचालित रूप से Equatable के अनुरूप नहीं है, भले ही उनके मान Equatable हैं। हालांकि, जब आप सीधे सरणी का उपयोग करते हैं, तो संकलक प्रकार से मिलान करने का प्रयास करता है और सरणी को NSArray में परिवर्तित करता है जो Equatable के अनुरूप होता है।

+0

यह है! वाह, यह मुझे कुछ समय के लिए परेशान कर रहा है! धन्यवाद! – vopilif

+1

दरअसल, इसके साथ कुछ और खेलना .. क्या आप वाकई इसे एनएसएआरएआरए में परिवर्तित कर रहे हैं? अगर मैं 'आयात फाउंडेशन' को हटा देता हूं तो मैं अब एनएसएआरएआरई का उपयोग नहीं कर सकता, लेकिन '[1,2,3] == [1,2,3] 'अभी भी काम करता है इसलिए कुछ और चलना चाहिए। – vopilif

+1

@ vopilif 'एलिमेंट: इक्विटेबल 'के साथ Arrays के लिए परिभाषित' ==' है। इसका मतलब यह नहीं है कि ऐरे 'इक्टेबल' लागू करता है। – Sulthan

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