मेरे पास यह कस्टम ऑपरेटर है:

infix operator ?> : NilCoalescingPrecedence
func ?> (lhs: Any?, rhs: @autoclosure ()->Any) {
    if lhs == nil {
        print("lhs is nil")
        rhs()
    }
}

उपयोग:

optional ?> {
    print("executing")
}

समस्या यह है, जब lhs शून्य है, तो क्लोजर निष्पादित नहीं हो रहा है। कंसोल में "एलएचएस शून्य है" प्रिंट कर रहा है, लेकिन बाद में कोई "निष्पादन" प्रिंट नहीं हो रहा है। "lhs is nil" प्रिंट स्टेटमेंट को कैसे निष्पादित किया जाता है लेकिन rhs को नहीं?

1
shoe 21 जुलाई 2017, 10:42

4 जवाब

सबसे बढ़िया उत्तर

ऐसा लगता है कि समाधान बिल्कुल उसी हस्ताक्षर के साथ ऑपरेटर को एक अधिभार जोड़ता है, सिवाय इसके कि इसमें @autoclosure एनोटेशन नहीं है, और rhs दोनों के लिए Void Any के बजाय।

infix operator ?> : NilCoalescingPrecedence
func ?> (lhs: Any?, rhs: @autoclosure ()->Void) {
    if lhs == nil {
        print("lhs is nil")
        rhs()
    }
}
func ?> (lhs: Any?, rhs: ()->Void) {
    if lhs == nil {
        print("lhs is nil")
        rhs()
    }
}

इस तरह अगर मैं करता हूं:

optional ?> doSomething()

@autoclosure को कॉल किया जाएगा, भले ही doSomething() कुछ भी लौटाए या नहीं।

और अगर मैं करता हूं:

optional ?> {
    doSomething()
    doSomethingElse()
}

बिना @autoclosure वाले को कॉल किया जाएगा क्योंकि क्लोजर ()->Void प्रकार का है।

1
shoe 22 जुलाई 2017, 02:37

जो चीज इस व्यवहार का कारण बनती है वह है @autoclosure, अगर आप इसे हटाते हैं, तो यह ठीक काम करता है।

ऐसा इसलिए है क्योंकि @autoclosure आपके क्लोजर को क्लोजर में लपेट देगा, इसलिए अब आपके पास कुछ इस तरह है:

{ { print("executing") } }

बाहरी बंद रिटर्न Any, है ना? तो यह सिर्फ { print("executing") } को बंद कर देगा और कुछ नहीं करेगा।

यदि आप @autoclosure रखना चाहते हैं, तो आप इस तरह से ऑपरेटर का उपयोग कर सकते हैं:

optional ?> print("executing")
2
Sweeper 21 जुलाई 2017, 10:55

आपको बंद करने की विधि के अंत में () जोड़ने की आवश्यकता है जैसे नीचे दी गई है

optional ?> {
    print("executing")
}()
0
Malik 21 जुलाई 2017, 10:50

यदि आपका इरादा है कि घुंघराले ब्रेसिज़ को ऑपरेटर के बाद जोड़ा जाना चाहिए, तो आप इसे (rhs को ऑटोक्लोज़र के रूप में घोषित किए बिना) लागू कर सकते हैं:

infix operator ?> : NilCoalescingPrecedence

func ?> (lhs: Any?, rhs: ()->Any) {
    if lhs == nil {
        print("lhs is nil")
        rhs()
    }
}

var myString: String? = ""

// some case that made "string" to be nil...
myString = nil

myString ?> {
    print("executing")
}

हालांकि, ऑटोक्लोजर घोषित करने का उद्देश्य एक अभिव्यक्ति को लपेटना है जिसे किसी फ़ंक्शन के तर्क के रूप में पारित किया जा रहा है:

यह वाक्य-विन्यास सुविधा आपको एक स्पष्ट क्लोजर के बजाय एक सामान्य अभिव्यक्ति लिखकर फ़ंक्शन के पैरामीटर के आसपास ब्रेसिज़ को छोड़ने देती है।

आधिकारिक स्विफ्ट दस्तावेज़ीकरण - क्लोजर, ऑटोक्लोजर

जिसका अर्थ है कि घुंघराले ब्रेसिज़ की कोई आवश्यकता नहीं है, जो एक ऑपरेटर के साथ काम करते समय अधिक स्वाभाविक होना चाहिए:

infix operator ?> : NilCoalescingPrecedence

func ?> (lhs: Any?, rhs: @autoclosure ()->Any) {
    if lhs == nil {
        print("lhs is nil")
        rhs()
    }
}

 var myString: String? = ""

 // some case that made "string" to be nil...
 myString = nil

// you could use your operator like:
 myString ?> print("executing")

लेकिन रुकिए!

एक समस्या का सामना करना पड़ सकता है जो है: क्या होगा यदि ऑपरेटर के बाद कोड का एक हिस्सा जोड़ा जाना चाहिए?

ठीक है, इसमें कोई संदेह नहीं है कि आपको घुंघराले ब्रेसिज़ जोड़ना होगा:

let doSomething = {
    print("executing")
    print("second line of execution")
    print("third line of execution")
}

myString ?> doSomething()
0
Ahmad F 21 जुलाई 2017, 11:36