मेरे पास यह कस्टम ऑपरेटर है:
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
को नहीं?
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
प्रकार का है।
जो चीज इस व्यवहार का कारण बनती है वह है @autoclosure
, अगर आप इसे हटाते हैं, तो यह ठीक काम करता है।
ऐसा इसलिए है क्योंकि @autoclosure
आपके क्लोजर को क्लोजर में लपेट देगा, इसलिए अब आपके पास कुछ इस तरह है:
{ { print("executing") } }
बाहरी बंद रिटर्न Any
, है ना? तो यह सिर्फ { print("executing") }
को बंद कर देगा और कुछ नहीं करेगा।
यदि आप @autoclosure
रखना चाहते हैं, तो आप इस तरह से ऑपरेटर का उपयोग कर सकते हैं:
optional ?> print("executing")
आपको बंद करने की विधि के अंत में ()
जोड़ने की आवश्यकता है जैसे नीचे दी गई है
optional ?> {
print("executing")
}()
यदि आपका इरादा है कि घुंघराले ब्रेसिज़ को ऑपरेटर के बाद जोड़ा जाना चाहिए, तो आप इसे (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()