संकलक त्रुटि स्विफ्ट: एक स्ट्रिंग समवर्ती पर "अभिव्यक्ति बहुत जटिल"


143

मुझे यह सब कुछ से अधिक मनोरंजक लगता है। मैंने इसे ठीक कर लिया है, लेकिन मैं इस कारण के बारे में सोच रहा हूं। यहाँ त्रुटि है: DataManager.swift:51:90: Expression was too complex to be solved in reasonable time; consider breaking up the expression into distinct sub-expressions। इसकी शिकायत क्यों है? यह संभव सबसे सरल अभिव्यक्तियों में से एक जैसा लगता है।

संकलक columns + ");";अनुभाग को इंगित करता है

func tableName() -> String { return("users"); } 

func createTableStatement(schema: [String]) -> String {

    var schema = schema;

    schema.append("id string");
    schema.append("created integer");
    schema.append("updated integer");
    schema.append("model blob");

    var columns: String = ",".join(schema);

    var statement = "create table if not exists " + self.tableName() + "(" + columns + ");";

    return(statement);
}

तय है:

var statement = "create table if not exists " + self.tableName();
statement += "(" + columns + ");";

यह भी काम करता है (@efischency के माध्यम से) लेकिन मुझे यह उतना पसंद नहीं है क्योंकि मुझे लगता है कि यह (खो गया है:

var statement = "create table if not exists \(self.tableName()) (\(columns))"


10
क्या आपने देखा कि क्या यह काम करता है var statement = "create table if not exists \(self.tableName()) (\(columns))":?
एफिशिएंसी

5
स्ट्रिंग इंटरपोलेशन, जैसा कि @ एफिशिएंसी द्वारा सुझाया गया है, आमतौर पर मैनुअल कॉन्टेनेशन से बेहतर विकल्प है +
मैटल

5
ज़रूर, लेकिन वह बात नहीं है। मुझे परवाह नहीं है कि यह "सुझाया गया" तरीका है या नहीं, मैं सिर्फ यह जानना चाहता हूं कि संकलक ने इस पर क्यों चुटकी ली। मेरे पास एक समाधान है जो काम करता है, यह त्रुटि को ठीक करने के बारे में नहीं है, यह त्रुटि को समझने के बारे में है।
केंड्रिक टेलर

2
मैंने जो सुना है, उसमें से स्विफ्ट कंपाइलर अभी भी बहुत काम है। टीम इस पर बग रिपोर्ट की सराहना कर सकती है।
मोलबडिलो

मेरे पास 6.3.1 के साथ इसे संकलित करने का कोई मुद्दा नहीं था। मेरे पास अतीत में ऐसे ही हास्यास्पद संदेश थे। हमें तब तक इंतजार करने की जरूरत है जब तक कि स्विफ्ट अपनी अल्फा स्थिति नहीं छोड़ देती।
qwerty_so

जवाबों:


183

मैं संकलक पर एक विशेषज्ञ नहीं हूं - मुझे नहीं पता कि यह उत्तर "परिवर्तन कैसे आप सार्थक तरीके से सोचते हैं," लेकिन समस्या की मेरी समझ यह है:

यह प्रकार के अनुमान के साथ करना है। हर बार जब आप +ऑपरेटर का उपयोग करते हैं , तो स्विफ्ट को सभी संभावित अधिभार के माध्यम से खोजना होगा +और यह पता लगाना होगा कि +आप किस संस्करण का उपयोग कर रहे हैं। मैंने +ऑपरेटर के लिए सिर्फ 30 ओवरलोड की गिनती की । यह बहुत सारी संभावनाएं हैं, और जब आप 4 या 5 +ऑपरेशनों को एक साथ करते हैं और कंपाइलर से सभी तर्कों का अनुमान लगाने के लिए कहते हैं, तो आप पहली नज़र में प्रकट होने की तुलना में बहुत अधिक पूछ रहे हैं।

यह अनुमान जटिल हो सकता है - उदाहरण के लिए, यदि आप UInt8एक Intका उपयोग कर जोड़ते हैं +, तो आउटपुट एक होगा Int, लेकिन कुछ काम है जो ऑपरेटरों के साथ प्रकारों के मिश्रण के नियमों का मूल्यांकन करने में जाता है।

और जब आप Stringअपने उदाहरण में शाब्दिक की तरह, शाब्दिक का उपयोग कर रहे हैं , तो संकलक Stringशाब्दिक को एक में परिवर्तित Stringकरने का कार्य कर रहा है, और फिर तर्क को समझाने और +परिचालक के लिए रिटर्न प्रकार आदि का काम कर रहा है ।

यदि एक अभिव्यक्ति पर्याप्त रूप से जटिल है - अर्थात, इसे तर्क और ऑपरेटरों के बारे में बहुत सारे निष्कर्ष बनाने के लिए कंपाइलर की आवश्यकता होती है - यह क्विट करता है और आपको बताता है कि इसे छोड़ दिया।

एक बार अभिव्यक्ति के जटिलता के एक निश्चित स्तर तक पहुंचने के बाद कंपाइलर का छोड़ना जानबूझकर होता है। विकल्प यह है कि संकलक को प्रयास करने दें और इसे करें, और देखें कि क्या यह हो सकता है, लेकिन यह जोखिम भरा है - संकलक हमेशा के लिए प्रयास कर सकता है, नीचे गिर सकता है, या बस दुर्घटनाग्रस्त हो सकता है। तो मेरी समझ यह है कि एक अभिव्यक्ति की जटिलता के लिए एक स्थिर सीमा है कि संकलक इससे आगे नहीं जाएगा।

मेरी समझ यह है कि स्विफ्ट टीम संकलक अनुकूलन पर काम कर रही है जो इन त्रुटियों को कम सामान्य बना देगा। आप इस लिंक पर क्लिक करके Apple डेवलपर मंचों पर इसके बारे में थोड़ा जान सकते हैं

देव मंचों पर, क्रिस लैटनर ने लोगों को इन त्रुटियों को रडार रिपोर्ट के रूप में दर्ज करने के लिए कहा है, क्योंकि वे सक्रिय रूप से उन्हें ठीक करने पर काम कर रहे हैं।

इसके बारे में और देव मंच पर इसके बारे में कई पोस्ट पढ़ने के बाद मैं इसे कैसे समझता हूं, लेकिन संकलक के बारे में मेरी समझ भोली है, और मैं उम्मीद कर रहा हूं कि कोई व्यक्ति इन कार्यों को कैसे संभालता है, इसका गहन ज्ञान होगा यहाँ लिखा है।


मैंने उस प्रभाव के बारे में कुछ सोचा, लेकिन यह एक उपयोगी उत्तर था, कम नहीं। जवाब के लिए धन्यवाद। क्या आपने हाथ से + संचालकों की संख्या की गणना की है या क्या कोई ऐसा तरीका है जिससे मैं अवगत नहीं हूं?
केंड्रिक टेलर 18

मैंने बस SwiftDoc.org पर इसे देखा और उन्हें हाथ से गिना। यह वह पृष्ठ है जिसके बारे में मैं बात कर रहा हूँ: swiftdoc.org/operator/pls
हारून रासमुसेन

28
यह एक बग है, चाहे वे इसे कहेंगे। अन्य भाषाओं के संकलक को कोड के समान कोई समस्या नहीं है जो पोस्ट की गई थी। अंतिम उपयोगकर्ता को सुझाव देना चाहिए कि यह मूर्खतापूर्ण है।
जॉन

7
प्रकार का अनुमान? इस तेजतर्रार स्थिति में स्विफ्ट जैसी मजबूत टाइप की हुई भाषा (जिसमें आप स्ट्रिंग + इंट को भी शामिल नहीं कर सकते हैं) को मजबूत करने वाली भाषा क्या है? एक बार फिर, स्विफ्ट उन समस्याओं को हल करने की कोशिश करती है जो पहले किसी के पास नहीं थी।
अजुरलेक

10
@ जॉन नहीं एक बग, बस खराब भाषा डिजाइन अगर तुम मुझसे पूछो! स्विफ्ट बहुत दूर जाता है बस अलग होने की कोशिश कर रहा है।
टी। रेक्स

31

यह लगभग स्वीकृत उत्तर के समान है लेकिन कुछ अतिरिक्त संवादों के साथ (मैं रोब नेपियर, उनके अन्य उत्तर और मैट, ओलिवर, स्लैक से डेविड) और लिंक के साथ था।

इस चर्चा में टिप्पणियों को देखें । इसका सार यह है:

+ भारी भरकम है (कुछ मामलों के लिए Apple ने यह तय किया है)

+ऑपरेटर भारी ओवरलोड हो गया है, अब के रूप में यह 27 विभिन्न कार्यों इसलिए यदि आप श्रृंखलाबद्ध कर रहे हैं 4 तार अर्थात आप 3 +ऑपरेटरों संकलक गया है की जाँच 27 ऑपरेटरों हर बार के बीच है, ताकि 27 ^ 3 बार है। लेकिन ऐसा नहीं है।

वहाँ भी एक है की जांच करता है, तो देखने के लिए lhsऔर rhsके +कार्यों दोनों वैध अगर वे इसे कोर के माध्यम से कॉल कर रहे हैं appendकहा जाता है। वहाँ आप देख सकते हैं कि कुछ गहन जाँचें हो सकती हैं। यदि स्ट्रिंग को गैर-सन्निहित रूप से संग्रहीत किया जाता है, जो ऐसा प्रतीत होता है यदि आप जिस स्ट्रिंग के साथ काम कर रहे हैं वह वास्तव में NSString के लिए ब्रिज किया गया है। तब स्विफ्ट को सभी बाइट सरणी बफ़र्स को एक एकल सन्निहित बफर में फिर से इकट्ठा करना पड़ता है और इसके लिए नए बफ़र्स बनाने की आवश्यकता होती है। और फिर आपको अंततः एक बफर मिलता है जिसमें वह स्ट्रिंग होती है जिसे आप एक साथ जोड़ने का प्रयास कर रहे होते हैं।

संक्षेप में, कंपाइलर चेक के 3 क्लस्टर हैं जो आपको धीमा कर देंगे अर्थात प्रत्येक उप-अभिव्यक्ति को हर उस चीज़ के प्रकाश में पुनर्विचार करना होगा जो वह वापस आ सकती है । एक परिणाम के रूप में प्रक्षेप के साथ तार को जोड़ने का उपयोग " My fullName is \(firstName) \(LastName)"करना यानी का उपयोग करना बेहतर है "My firstName is" + firstName + LastNameक्योंकि प्रक्षेप से कोई अतिभार नहीं होता है

स्विफ्ट 3 में कुछ सुधार किए गए हैं । अधिक जानकारी के लिए नीचे संकलक को धीमा किए बिना कई एरे को कैसे मर्ज करें? । फिर भी, +ऑपरेटर अभी भी अतिभारित है और लंबे समय तक तार के लिए स्ट्रिंग प्रक्षेप का उपयोग करना बेहतर है


वैकल्पिक का उपयोग (चल रही समस्या - समाधान उपलब्ध)

इस बहुत ही सरल परियोजना में:

import UIKit

class ViewController: UIViewController {

    let p = Person()
    let p2 = Person2()

    func concatenatedOptionals() -> String {
        return (p2.firstName ?? "") + "" + (p2.lastName ?? "") + (p2.status ?? "")
    }

    func interpolationOptionals() -> String {
        return "\(p2.firstName ?? "") \(p2.lastName ?? "")\(p2.status ?? "")"
    }

    func concatenatedNonOptionals() -> String {
        return (p.firstName) + "" + (p.lastName) + (p.status)
    }

    func interpolatedNonOptionals() -> String {
        return "\(p.firstName) \(p.lastName)\(p.status)"
    }
}


struct Person {
    var firstName = "Swift"
    var lastName = "Honey"
    var status = "Married"
}

struct Person2 {
    var firstName: String? = "Swift"
    var lastName: String? = "Honey"
    var status: String? = "Married"
}

कार्यों के लिए संकलन समय इस प्रकार है:

21664.28ms  /Users/Honey/Documents/Learning/Foundational/CompileTime/CompileTime/ViewController.swift:16:10 instance method concatenatedOptionals()
2.31ms  /Users/Honey/Documents/Learning/Foundational/CompileTime/CompileTime/ViewController.swift:20:10 instance method interpolationOptionals()
0.96ms  /Users/Honey/Documents/Learning/Foundational/CompileTime/CompileTime/ViewController.swift:24:10 instance method concatenatedNonOptionals()
0.82ms  /Users/Honey/Documents/Learning/Foundational/CompileTime/CompileTime/ViewController.swift:28:10 instance method interpolatedNonOptionals()

ध्यान दें कि पागल अवधि के लिए संकलन अवधि कितनी अधिक concatenatedOptionalsहै।

इसे करने से हल किया जा सकता है:

let emptyString: String = ""
func concatenatedOptionals() -> String {
    return (p2.firstName ?? emptyString) + emptyString + (p2.lastName ?? emptyString) + (p2.status ?? emptyString)
}

जिसमें संकलन है 88ms

समस्या का मूल कारण यह है कि संकलक ""एक के रूप में पहचान नहीं करता है String। यह वास्तव में हैExpressibleByStringLiteral

कंपाइलर देखेगा ??और सभी प्रकार के माध्यम से लूप करना होगा जो इस प्रोटोकॉल के अनुरूप है , जब तक कि वह एक प्रकार नहीं पाता है जो कि डिफ़ॉल्ट हो सकता है StringemptyStringजिसके उपयोग से हार्डकोड किया जाता है String, कंपाइलर को सभी अनुरूप प्रकारों के माध्यम से लूप करने की आवश्यकता नहीं हैExpressibleByStringLiteral

संकलन समय लॉग करने के लिए सीखने के लिए यहां या यहां देखें


एसओ पर रोब नेपियर के अन्य समान जवाब:

स्ट्रिंग को बनाने में इतना समय क्यों लगता है?

कंपाइलर को धीमा किए बिना कई एरे को कैसे मर्ज किया जाए?

स्विफ्ट एरे में फ़ंक्शन होता है जो बिल्ड समय को लंबा करता है


19

यह काफी हास्यास्पद है कि आप क्या कहते हैं! :)

यहां छवि विवरण दर्ज करें

लेकिन यह आसानी से पास हो जाता है

return "\(year) \(month) \(dayString) \(hour) \(min) \(weekDay)"

2

मेरे पास भी ऐसा ही मुद्दा था:

expression was too complex to be solved in reasonable time; consider breaking up the expression into distinct sub-expressions

Xcode में 9.3 लाइन इस प्रकार है:

let media = entities.filter { (entity) -> Bool in

इसे कुछ इस तरह से बदलने के बाद:

let media = entities.filter { (entity: Entity) -> Bool in

सब कुछ काम कर गया।

संभवतः इसके पास स्विफ्ट कंपाइलर के साथ कोड से डेटा प्रकार का अनुमान लगाने की कोशिश करने के लिए कुछ है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.