रूबी विधियों में विस्मयादिबोधक चिह्न का उपयोग क्यों किया जाता है?


540

रूबी में कुछ विधियों में एक प्रश्न चिह्न ( ?) होता है जो एक प्रश्न पूछता है जैसे include?कि पूछें कि क्या प्रश्न में वस्तु शामिल है, तो यह सही या गलत है।

लेकिन कुछ विधियों में विस्मयादिबोधक चिह्न ( !) क्यों हैं, जहां अन्य नहीं हैं?

इसका क्या मतलब है?


21
पर्यायवाची: बैंग, विस्मयादिबोधक चिह्न
प्रसंग

17
स्वीकृत उत्तर को stackoverflow.com/a/612653/109618 पर बदलना चाहिए । देखें wobblini.net/bang.txt और ruby-forum.com/topic/176830#773946 - "धमाकेदार संकेत का अर्थ है" धमाके का संस्करण अपने गैर धमाके समकक्ष की तुलना में अधिक खतरनाक है; संभाल के साथ संभाल "" -Matz
डेविड जे।

2
धमाका विधि एक महान डिजाइन विकल्प होगा यदि केवल और सभी धमाके के तरीके खतरनाक थे। अफसोस की बात है कि वे नहीं हैं, और इसलिए यह याद रखने में एक निराशाजनक अभ्यास बन जाता है कि क्या है और क्या नहीं।
डेमियन रोशे

जवाबों:


617

सामान्य तौर पर, विधियाँ जो यह !बताती हैं कि यह विधि उस वस्तु को संशोधित करेगी जो इसे कहा जाता है । रूबी ने इन्हें " खतरनाक तरीके " कहा, क्योंकि वे यह बताते हैं कि किसी और का संदर्भ हो सकता है। यहाँ तार के लिए एक सरल उदाहरण है:

foo = "A STRING"  # a string called foo
foo.downcase!     # modifies foo itself
puts foo          # prints modified foo

यह आउटपुट होगा:

a string

मानक पुस्तकालयों में, बहुत सारे स्थान हैं जहाँ आप समान नाम वाली विधियों के जोड़े देखेंगे, एक के !बिना और एक के साथ । बिना लोगों को "सुरक्षित तरीकों" कहा जाता है, और वे परिवर्तन के साथ मूल की एक प्रति के लिए आवेदन किया लौट प्रतिलिपि , कॉल प्राप्त करने वाला कोई बदलाव नहीं है। यहाँ एक ही उदाहरण के बिना है !:

foo = "A STRING"    # a string called foo
bar = foo.downcase  # doesn't modify foo; returns a modified string
puts foo            # prints unchanged foo
puts bar            # prints newly created bar

यह आउटपुट:

A STRING
a string

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


2
बाहर निकलने बनाम बाहर निकलने जैसे मामले भी हैं! (और रेल में) बनाम बचाओ बचाओ!
एंड्रयू ग्रिम

24
बहुत सावधान रहें - कई छोटे पुस्तकालय इस सम्मेलन का पालन नहीं करते हैं। यदि अजीब चीजें हो रही हैं, तो अक्सर obj.whatever की जगह लें! with obj = obj.whatever! इसे ठीक करता है। अधिक निराश।
सारा मेई

101
धमाके भी तरीकों कि एक अपवाद जुटाने के लिए प्रयोग किया जाता है जब विधि के बिना नहीं करता है, जैसे: saveऔर save!मेंActiveRecord
ecoologic

3
@ अखिलेश बचाओ! यदि यह सहेज नहीं सकता है तो एक त्रुटि उठाता है। यह नियमित रूप से सही / गलत वापस लौटने का विरोध करता है।
बुकऑफग्रेग

31
@tgamblin रूबी में बहुत सारे तरीके हैं जो बैंग्स के बिना म्यूट करते हैं। वहाँ भी दुर्लभ तरीके हैं जो एक धमाके के साथ उत्परिवर्तन नहीं करते हैं लेकिन कुछ आश्चर्यजनक करते हैं जैसे त्रुटियों को बढ़ाएं या त्रुटियों को छोड़ दें। बैंग्स का उपयोग यह कहने के लिए किया जाता है कि यह विधि का अधिक असामान्य संस्करण है और मुझे लगता है कि इसे आपके उत्तर में प्रतिबिंबित किया जाना चाहिए क्योंकि यह सही के रूप में चिह्नित है।
बुकऑफग्रेग

143

विस्मयादिबोधक बिंदु का अर्थ है कई चीजें, और कभी-कभी आप इसे "यह खतरनाक है, सावधान रहें" के अलावा इससे बहुत कुछ नहीं बता सकते हैं।

जैसा कि दूसरों ने कहा है, मानक तरीकों में इसका उपयोग अक्सर एक ऐसी विधि को इंगित करने के लिए किया जाता है जो किसी वस्तु को स्वयं को बदलने का कारण बनता है, लेकिन हमेशा नहीं। नोट कई मानक तरीकों उनके रिसीवर बदल कि और एक विस्मयादिबोधक बिंदु (की जरूरत नहीं है pop, shift, clear), और विस्मयादिबोधक अंक के साथ कुछ तरीकों उनके रिसीवर में परिवर्तन नहीं करते ( exit!)। इस लेख को उदाहरण के लिए देखें ।

अन्य पुस्तकालय इसका अलग-अलग उपयोग कर सकते हैं। रेल में एक विस्मयादिबोधक बिंदु का अर्थ अक्सर यह होता है कि विधि चुपचाप विफल होने के बजाय विफलता पर एक अपवाद फेंक देगी।

यह एक नामकरण सम्मेलन है लेकिन बहुत से लोग इसका उपयोग अलग-अलग तरीकों से करते हैं। अपने स्वयं के कोड में अंगूठे का एक अच्छा नियम इसका उपयोग करना है जब भी कोई विधि कुछ "खतरनाक" कर रही है, खासकर जब एक ही नाम वाले दो तरीके मौजूद हों और उनमें से एक दूसरे की तुलना में अधिक "खतरनाक" हो। "खतरनाक" का अर्थ लगभग कुछ भी हो सकता है।


75

इस नामकरण सम्मेलन को योजना से हटा दिया गया है

1.3.5 नामकरण सम्मेलन

कन्वेंशन द्वारा, प्रक्रियाओं के नाम जो हमेशा एक बूलियन मान लौटाते हैं, आमतौर पर ``? '' में समाप्त होते हैं। ऐसी प्रक्रियाओं को विधेय कहा जाता है।

अधिवेशन द्वारा, प्रक्रियाओं के नाम जो पहले आवंटित स्थानों में मूल्यों को संग्रहीत करते हैं (अनुभाग 3.4 देखें) आमतौर पर ``! '' में समाप्त होते हैं। ऐसी प्रक्रियाओं को उत्परिवर्तन प्रक्रिया कहा जाता है। सम्मेलन द्वारा, एक उत्परिवर्तन प्रक्रिया द्वारा लौटाया गया मान अनिर्दिष्ट है।


2
इस उत्तर के लिए +1 के बाद से एक प्रलेखन है जो के लिए उचित स्पष्टीकरण देता है! उपयोग। वास्तव में अच्छा उत्तर स्टीवन
डेविडविल्विरा 15

धन्यवाद @DavidSilveira!
स्टीवन हुआविग

24

! आम तौर पर इसका मतलब है कि विधि परिणाम पर लौटने के बजाय ऑब्जेक्ट पर कार्य करती है। पुस्तक प्रोग्रामिंग रूबी से :

वे तरीके जो "खतरनाक" हैं या रिसीवर को संशोधित करते हैं, उनका नाम अनुगामी के साथ रखा जा सकता है "!"।


18

यह कहना सही है कि बैंग के साथ तरीके! अधिक खतरनाक या आश्चर्यजनक संस्करण हैं। ऐसे कई तरीके हैं जो एक बैंग के बिना उत्परिवर्तित करते हैं जैसे कि .destroyऔर सामान्य तरीकों में केवल बैंग्स होते हैं जहां कोर लिबर में एक सुरक्षित विकल्प मौजूद होता है।

उदाहरण के लिए, ऐरे पर हमारे पास .compactऔर .compact!, दोनों विधियाँ सरणी को बदल देती हैं, लेकिन .compact!यदि सरणी में कोई शून्य नहीं है, तो स्वयं के बजाय शून्य लौटाता है, जो कि केवल स्वयं लौटने से अधिक आश्चर्य की बात है।

केवल गैर-परिवर्तनशील विधि मैं एक धमाके के साथ मिल गया है है Kernelकी .exit!जो भी अधिक आश्चर्य की बात है .exitक्योंकि आप नहीं पकड़ सकते SystemExit, जबकि प्रक्रिया बंद हो रहा है।

रेल और ActiveRecord इस प्रवृत्ति को जारी रखता है कि यह अधिक 'आश्चर्यजनक' प्रभावों के लिए धमाके का उपयोग करता है जैसे .create!विफलता पर त्रुटियों को बढ़ाता है।


16

Themomorohoax.com से:

मेरी व्यक्तिगत पसंद के क्रम में, नीचे दिए गए तरीकों से एक बैंग का उपयोग किया जा सकता है।

1) एक सक्रिय रिकॉर्ड विधि एक त्रुटि उठाती है यदि विधि ऐसा नहीं करती है जो यह कहती है कि यह होगा।

2) एक सक्रिय रिकॉर्ड विधि रिकॉर्ड को बचाता है या एक विधि किसी वस्तु को बचाता है (जैसे पट्टी!)

3) एक विधि कुछ "अतिरिक्त" करती है, जैसे कि कुछ स्थानों पर पोस्ट, या कुछ क्रिया।

मुद्दा यह है: केवल एक धमाके का उपयोग करें जब आपने वास्तव में सोचा है कि क्या यह आवश्यक है, अन्य डेवलपर्स को बचाने के लिए कि आप धमाके का उपयोग क्यों कर रहे हैं यह जांचने की झुंझलाहट को बचाएं।

बैंग अन्य डेवलपर्स को दो संकेत प्रदान करता है।

1) यह विधि को कॉल करने के बाद ऑब्जेक्ट को बचाने के लिए आवश्यक नहीं है।

2) जब आप विधि को कॉल करते हैं, तो db को बदलने जा रहा है।

http://www.themomorohoax.com/2009/02/11/when-to-use-a-bang-exclamation-point-after-rails-methods


6

सरल स्पष्टीकरण:

foo = "BEST DAY EVER" #assign a string to variable foo.

=> foo.downcase #call method downcase, this is without any exclamation.

"best day ever"  #returns the result in downcase, but no change in value of foo.

=> foo #call the variable foo now.

"BEST DAY EVER" #variable is unchanged.

=> foo.downcase! #call destructive version.

=> foo #call the variable foo now.

"best day ever" #variable has been mutated in place.

लेकिन अगर आप कभी भी downcase!ऊपर दिए गए स्पष्टीकरण में एक विधि कहते हैं , fooतो स्थायी रूप से नीचे की ओर बदल जाएगा। downcase!एक नया स्ट्रिंग ऑब्जेक्ट नहीं लौटाएगा लेकिन स्ट्रिंग को जगह में बदल देगा, पूरी तरह fooसे डाउनकेस में बदल देगा । मेरा सुझाव है कि आप downcase!तब तक उपयोग न करें जब तक कि यह पूरी तरह से आवश्यक न हो।


1
!

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

यदि आप उदाहरण के लिए रूबी की विधि वैश्विक प्रतिस्थापन gsub!के लिए उपयोग करते हैं तो आपके द्वारा किए गए प्रतिस्थापन स्थायी हैं।

एक और तरीका है जिसकी आप कल्पना कर सकते हैं, एक टेक्स्ट फ़ाइल खोल रहा है और खोज और प्रतिस्थापित कर रहा है, उसके बाद बचत। !आपके कोड में समान है।

एक अन्य उपयोगी अनुस्मारक यदि आप बैश दुनिया से आते हैं तो sed -iस्थायी रूप से सहेजे गए परिवर्तन करने का यह समान प्रभाव है।


1

"विनाशकारी तरीके" कहा जाता है, वे उस वस्तु की मूल प्रति को बदलते हैं जिसका आप उल्लेख कर रहे हैं।

numbers=[1,0,10,5,8]
numbers.collect{|n| puts n*2} # would multiply each number by two
numbers #returns the same original copy
numbers.collect!{|n| puts n*2} # would multiply each number by two and destructs the original copy from the array
numbers   # returns [nil,nil,nil,nil,nil]

0

नीचे की रेखा: !विधियाँ केवल उस वस्तु के मूल्य को बदल देती हैं, जिस पर उन्हें कहा जाता है, जबकि विधि के !बिना लिखी गई वस्तु के बिना एक हेरफेर किए गए मान को वापस करता है।

!यदि आप जिस चर को विधि कहते हैं, उस पर संग्रहीत मूल मूल्य की आवश्यकता होने पर ही उपयोग न करें।

मैं कुछ करना पसंद करता हूं:

foo = "word"
bar = foo.capitalize
puts bar

या

foo = "word"
puts foo.capitalize

के बजाय

foo = "word"
foo.capitalize!
puts foo

बस के मामले में मैं मूल मूल्य को फिर से एक्सेस करना चाहूंगा।


1
क्योंकि आपका जवाब किसी भी तरह से मददगार नहीं था। "नीचे की रेखा: - विधियाँ केवल उस वस्तु के मूल्य को बदल देती हैं जिस पर उन्हें बुलाया जाता है" बस सत्य नहीं है।
डार्विन

@Darwin यह करता है वस्तु के मूल्य बदल जाते हैं। !संशोधित प्रति वापस करने के बजाय ऑब्जेक्ट को म्यूट करता है।
चार्ल्स

तो आपको क्या लगता है यह क्या करता है? User.create!
डार्विन

@ डार्विन किस संदर्भ में? ActiveRecord?
चार्ल्स

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