मुझे स्विफ्ट में अंडरस्कोर की आवश्यकता क्यों है?


161

यहाँ यह कहता है, "नोट: द_ इसका मतलब है" मुझे उस मूल्य की परवाह नहीं है ", लेकिन जावास्क्रिप्ट से आने पर, मुझे समझ में नहीं आता कि इसका क्या मतलब है।

जिस तरह से मैं प्रिंट करने के लिए इन कार्यों को प्राप्त कर सकता हूं वह मापदंडों से पहले अंडरस्कोर का उपयोग करके था:

func divmod(_ a: Int, _ b:Int) -> (Int, Int) {
    return (a / b, a % b)
}

print(divmod(7, 3))
print(divmod(5, 2))
print(divmod(12,4))

अंडरस्कोर के बिना मुझे किसी भी त्रुटि से बचने के लिए इसे इस तरह लिखना होगा:

func divmod(a: Int, b:Int) -> (Int, Int) {
    return (a / b, a % b)
}

print(divmod(a: 7, b: 3))
print(divmod(a: 5, b: 2))
print(divmod(a: 12,b: 4))

मैं इस अंडरस्कोर उपयोग को नहीं समझता। कब, कैसे और क्यों मैं इन अंडरस्कोर का उपयोग करता हूं?

जवाबों:


353

विभिन्न उपयोग के मामलों में कुछ बारीकियां हैं, लेकिन आम तौर पर एक अंडरस्कोर का अर्थ है "इसे अनदेखा करें"।


एक नए फ़ंक्शन की घोषणा करते समय, एक अंडरस्कोर स्विफ्ट को बताता है कि जब कॉल किया जाता है तो पैरामीटर को कोई लेबल नहीं होना चाहिए - यही स्थिति आप देख रहे हैं। एक फुलर फ़ंक्शन घोषणा इस तरह दिखती है:

func myFunc(label name: Int) // call it like myFunc(label: 3)

"लेबल" एक तर्क लेबल है, और फ़ंक्शन को कॉल करने पर मौजूद होना चाहिए। (और स्विफ्ट 3 के बाद से, डिफ़ॉल्ट रूप से सभी तर्कों के लिए लेबल आवश्यक हैं।) "नाम" उस तर्क के लिए चर नाम है जिसे आप फ़ंक्शन के अंदर उपयोग करते हैं। एक छोटा रूप इस तरह दिखता है:

func myFunc(name: Int) // call it like myFunc(name: 3)

यह एक शॉर्टकट है जो आपको बाहरी तर्क लेबल और आंतरिक पैरामीटर नाम दोनों के लिए एक ही शब्द का उपयोग करने देता है। इसके बराबर है func myFunc(name name: Int)

यदि आप चाहते हैं कि आपका फ़ंक्शन पैरामीटर लेबल के बिना कॉल करने योग्य हो, तो आप _लेबल को कुछ भी अनदेखा / अनदेखा करने के लिए अंडरस्कोर का उपयोग न करें । (यदि आप पैरामीटर का उपयोग करने में सक्षम होना चाहते हैं तो उस स्थिति में आपको एक आंतरिक नाम प्रदान करना होगा।)

func myFunc(_ name: Int) // call it like myFunc(3)

असाइनमेंट स्टेटमेंट में, एक अंडरस्कोर का अर्थ है "कुछ भी असाइन न करें"। आप इसका उपयोग कर सकते हैं यदि आप एक फ़ंक्शन को कॉल करना चाहते हैं जो एक परिणाम देता है लेकिन लौटे मूल्य के बारे में परवाह नहीं करता है।

_ = someFunction()

या, आपके द्वारा लिंक किए गए लेख की तरह, एक लौटे हुए टपल के एक तत्व को अनदेखा करने के लिए:

let (x, _) = someFunctionThatReturnsXandY()

जब आप एक क्लोजर लिखते हैं जो कुछ परिभाषित फ़ंक्शन प्रकार को लागू करता है, तो आप कुछ मापदंडों को अनदेखा करने के लिए अंडरस्कोर का उपयोग कर सकते हैं।

PHPhotoLibrary.performChanges( { /* some changes */ },
    completionHandler: { success, _ in // don't care about error
        if success { print("yay") }
    })

इसी तरह, जब एक फ़ंक्शन घोषित किया जाता है जो एक प्रोटोकॉल को अपनाता है या एक सुपरक्लास विधि को ओवरराइड करता है, तो आप _पैरामीटर नामों की अनदेखी कर सकते हैं। चूंकि प्रोटोकॉल / सुपरक्लास यह भी परिभाषित कर सकते हैं कि पैरामीटर में कोई लेबल नहीं है, आप एक पंक्ति में दो अंडरस्कोर भी समाप्त कर सकते हैं।

class MyView: NSView {
    override func mouseDown(with _: NSEvent) {
        // don't care about event, do same thing for every mouse down
    }
    override func draw(_ _: NSRect) {
        // don't care about dirty rect, always redraw the whole view
    }
}

पिछले दो शैलियों से संबंधित: जब एक प्रवाह नियंत्रण निर्माण का उपयोग करता है जो एक स्थानीय चर / निरंतर को बांधता है, तो आप _इसे अनदेखा करने के लिए उपयोग कर सकते हैं । उदाहरण के लिए, यदि आप इसके सदस्यों तक पहुँच की आवश्यकता के बिना किसी क्रम को क्रमबद्ध करना चाहते हैं:

for _ in 1...20 { // or 0..<20
    // do something 20 times
}

यदि आप एक स्विच स्टेटमेंट में टपल मामलों को बांध रहे हैं, तो अंडरस्कोर वाइल्डकार्ड के रूप में काम कर सकता है, जैसा कि इस उदाहरण में ( द स्विफ्ट प्रोग्रामिंग लैंग्वेज में एक से छोटा ):

switch somePoint { // somePoint is an (Int, Int) tuple
case (0, 0):
    print("(0, 0) is at the origin")
case (_, 0):
    print("(\(somePoint.0), 0) is on the x-axis")
case (0, _):
    print("(0, \(somePoint.1)) is on the y-axis")
default:
    print("(\(somePoint.0), \(somePoint.1)) isn't on an axis")
}

एक आखिरी चीज जो काफी संबंधित नहीं है, लेकिन जो मैं शामिल करूंगा (जैसा कि टिप्पणियों द्वारा नोट किया गया है) यह यहां लोगों का नेतृत्व करने के लिए लगता है: एक पहचानकर्ता में एक अंडरस्कोर - उदाहरण var _fooके लिए func do_the_thing(), struct Stuff_- का मतलब विशेष रूप से स्विफ्ट के लिए कुछ भी नहीं है, लेकिन कुछ उपयोग हैं प्रोग्रामर के बीच।

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

अंडरस्कोर के साथ एक प्रतीक नाम को उपसर्ग या प्रत्यय देना एक शैली सम्मेलन है, जिसे ऐतिहासिक रूप से निर्यातित एपीआई से निजी / आंतरिक-उपयोग-केवल प्रतीकों को भेद करने के लिए उपयोग किया जाता है। हालाँकि, स्विफ्ट के पास इसके लिए संशोधक हैं, इसलिए इस सम्मेलन को आम तौर पर स्विफ्ट में गैर-मुहावरेदार के रूप में देखा जाता है।

func __foo()Apple के SDKs की गहराई में डबल-अंडरस्कोर उपसर्गों ( ) लर्क के साथ कुछ प्रतीक : ये NS_REFINED_FOR_SWIFTविशेषता का उपयोग करके स्विफ्ट में आयात किए गए (Obj) C प्रतीक हैं । Apple इसका उपयोग करता है जब वे एक (Obj) C API का "अधिक स्विफ्टी" संस्करण बनाना चाहते हैं - उदाहरण के लिए, एक जेनेरिक विधि में एक प्रकार-अज्ञेय विधि बनाने के लिए । परिष्कृत स्विफ्ट संस्करण को काम करने के लिए उन्हें आयातित एपीआई का उपयोग करने की आवश्यकता होती है, इसलिए वे __इसे अधिकांश टूल और प्रलेखन से छिपाते हुए इसे उपलब्ध रखने के लिए उपयोग करते हैं।


@rickster, एक विधि की शुरुआत में अंडरस्कोर का क्या महत्व है, जैसे यह एक-> func _copyContents (प्रारंभिक ptr: UnsafeMutableBufferPointer <Element>) -> (Iterator, UnsafeMutableBufferPointer <Element>। Indexex) से।
देव जीआर

@devgr: पूरी तरह से असंबंधित, इसलिए मैं एक अलग प्रश्न पोस्ट करने की सलाह दूंगा।
रिकस्टर

ज़रूर, मैं एक अलग सवाल पोस्ट करूंगा।
देव जीआर

फ़ंक्शन वापसी के लिए "कुछ भी असाइन न करें" के लिए धन्यवाद। यही मैं ढूंढ रहा था।
अनुपस्थित

8

स्वीकृत उत्तर के अलावा, उपयोग के मामलों में से _एक है जब आपको कोड में एक लंबी संख्या लिखने की आवश्यकता होती है

अधिक पठनीय संख्या

यह आसान मानव पठनीय नहीं है:

let x = 1000000000000

आप _इसे और अधिक मानव पठनीय बनाने के लिए संख्या में जोड़ सकते हैं :

let x = 1_000_000_000_000

6

स्विफ्ट 3 के बाद से, फ़ंक्शन कॉल पर पैरामीटर नाम निर्दिष्ट करना अनिवार्य हो गया है - यहां तक ​​कि पहले के लिए भी। इसलिए, क्योंकि यह स्विफ्ट 2 में लिखे कोड को भारी समस्या पैदा कर सकता है, आप कॉल पर पैरामीटर नाम लिखने से रोकने के लिए घोषणा पर एक अंडरस्कोर का उपयोग कर सकते हैं। तो इस मामले में, यह कह रहा है "बाहरी पैरामीटर नाम की परवाह न करें"। जहां बाहरी पैरामीटर नाम वह है जिसे आप फ़ंक्शन के बाहर पैरामीटर कहते हैं (कॉल पर) अंदर नहीं। इन बाहरी पैरामीटर नामों को तर्क लेबल कहा जाता है। http://ericasadun.com/2016/02/09/the-trouble-with-argument-labels-some- हालांकि ts/ ... देखते हैं कि पैरामीटर को दो नाम कैसे दिए जाते हैं? अच्छी तरह से पहले जहां अंडरस्कोर चल रहा है। यह मदद करता है, और पूछें कि क्या अभी भी भ्रमित है।


4
func divmod(_ a: Int, _ b:Int) -> (Int, Int) {
    return (a / b, a % b)
}

func divmod(a: Int, b:Int) -> (Int, Int) {
    return (a / b, a % b)
}

_पैरामीटर नाम के लिए एक प्लेसहोल्डर है। अपने उदाहरण में, आप उन्हें अलग तरीके से कॉल करते हैं, दूसरे फ़ंक्शन में, आपको पैरामीटर नाम लिखना होगा a: 1

स्विफ्ट का फ़ंक्शन नाम कन्वेंशन है funcName(param1:param2:), और इसे फ़ंक्शन का नाम _बनाने के लिए प्लेसहोल्डर के रूप में आवश्यकता होती है।

पहले नाम में, नाम है

divmod(_:_:)

जबकि दूसरा है

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