रूबी i ++ या i-- (वेतन वृद्धि / परिचालकों) का समर्थन क्यों नहीं करती है?


130

प्री / पोस्ट इन्क्रीमेंट / डिक्रीमेंट ऑपरेटर ( ++और --) सुंदर मानक प्रोग्रामिंग लैंग्वेज सिंटैक्स (प्रक्रियात्मक और ऑब्जेक्ट-ओरिएंटेड भाषाओं के लिए, कम से कम) हैं।

रूबी उनका समर्थन क्यों नहीं करती? मैं समझता हूँ कि आप के साथ एक ही बात को पूरा कर सकते +=हैं और -=, लेकिन यह सिर्फ ऐसा ही कुछ बाहर करने के लिए अजीब तरह से मनमाने ढंग से लगता है, खासकर जब से यह इतना संक्षिप्त और पारंपरिक है।

उदाहरण:

i = 0    #=> 0
i += 1   #=> 1
i        #=> 1
i++      #=> expect 2, but as far as I can tell, 
         #=> irb ignores the second + and waits for a second number to add to i

मैं समझता हूं कि Fixnumयह अपरिवर्तनीय है, लेकिन अगर +=किसी नए Fixnumको स्थापित कर सकते हैं और इसे सेट कर सकते हैं, तो इसके लिए क्यों नहीं ++?

क्या असाइनमेंट में स्थिरता =इसके लिए एकमात्र कारण है, या मुझे कुछ याद आ रहा है?


2
ऐसे ऑपरेटरों के लिए जीआरपी रूबी स्रोत कोड। यदि कोई नहीं हैं - तो Matz उन्हें पसंद नहीं करता है।
ईमंतस

आप किसी +=ऑपरेटर के साथ पूर्व-निर्धारण नहीं कर सकते । सीआई में मूल विवरण में अधिक शाब्दिक / के लिए अधिमानतः केवल सशर्त के अंदर ++/ उपयोग करने का प्रयास करें । शायद इसलिए कि मैंने अजगर (हालांकि सी के बाद लंबे समय तक ...)--+=-=
निक टी

क्या सिर्फ पायथन के लिए कल ही ऐसा सवाल नहीं था?
BoltClock

@Eimantas अच्छी तरह से जाहिर है कि भाषा के रचनाकार उन्हें पसंद नहीं करते थे। अनदेखी करना बहुत आम है। मैं क्यों सोच रहा था, जिसे नीचे दिए गए उत्तरों से स्पष्ट किया गया है।
एंडी_ वुल्फ

1
मुझे लगता है कि यह (लगभग) एक मॉडल SO प्रश्न है। यह ऐसा कुछ नहीं है जिसे आसानी से एक माना जवाब पाने के लिए googleable नहीं है। यह बहुत स्पष्ट और विशिष्ट है कि किस उत्तर की आवश्यकता है और उत्तर प्रोग्रामिंग के एक पहलू पर प्रकाश डालता है जो किसी प्रश्न के मूल से अधिक व्यापक रूप से सोच सकता है।
पर्पलिपॉट

जवाबों:


97

यहाँ बताया गया है कि कैसे Matz (Yukihiro Matsumoto) इसे एक पुराने सूत्र में समझाता है :

Hi,

In message "[ruby-talk:02706] X++?"
    on 00/05/10, Aleksi Niemelä <aleksi.niemela@cinnober.com> writes:

|I got an idea from http://www.pragprog.com:8080/rubyfaq/rubyfaq-5.html#ss5.3
|and thought to try. I didn't manage to make "auto(in|de)crement" working so
|could somebody help here? Does this contain some errors or is the idea
|wrong?

  (1) ++ and -- are NOT reserved operator in Ruby.

  (2) C's increment/decrement operators are in fact hidden assignment.
      They affect variables, not objects.  You cannot accomplish
      assignment via method.  Ruby uses +=/-= operator instead.

  (3) self cannot be a target of assignment.  In addition, altering
      the value of integer 1 might cause severe confusion throughout
      the program.

                            matz.

10
2 और 3 विरोधाभासी लगते हैं। यदि स्वयं असाइनमेंट खराब है, तो +=/ -=ठीक क्यों हैं ? और 1+=1बस के रूप में बुरा नहीं होगा ? (यह आईआरबी में विफल रहता है syntax error, unexpected ASSIGNMENT)
एंडी_ वुल्फ

2
(2) का अर्थ है कि C में, आप मान को परिवर्तित नहीं कर रहे हैं ... आप मान रखने वाले चर की सामग्री को बदल रहे हैं। यह किसी भी भाषा के लिए थोड़ा बहुत मेटा है जो मूल्य से गुजरता है। जब तक रूबी में संदर्भ द्वारा कुछ पास करने का एक तरीका नहीं है (और वास्तव में "संदर्भ द्वारा" का अर्थ है, मूल्य द्वारा संदर्भ नहीं पारित करना), चर को बदलना केवल एक विधि के भीतर संभव नहीं होगा।
cHao

5
शायद मुझे यहाँ कुछ याद आ रहा है। +=परिवर्तनशील वस्तु को पूरी नई वस्तु के साथ बदल देता है। आप इसे i.object_idपहले और बाद में कॉल करके चेक कर सकते हैं i+=1। ऐसा करने के लिए कोई और तकनीकी रूप से मुश्किल क्यों होगा ++?
एंडी_ वुल्फ

6
@Andy_Vulhop: # 3 समझा रहा है कि असाइनमेंट के लिए तकनीकी रूप से असंभव एक विधि है, न कि असाइनमेंट सामान्य रूप से असंभव क्यों है (पोस्टर मेत्ज़ ने उत्तर देते हुए सोचा था कि यह एक ++विधि बनाने के लिए संभव हो सकता है )।
चक

2
रूबी में सभी शाब्दिक वस्तुएं भी हैं। इसलिए मेरा मानना ​​है कि मैत्ज़ यह कहना चाह रहा है कि उसे यकीन नहीं है कि वह एक बयान के रूप में 1 ++ से निपटने के विचार को पसंद करता है। व्यक्तिगत रूप से मुझे लगता है कि यह अनुचित है क्योंकि @Andy_Vulhop का कहना है कि 1 + = 2 व्यर्थ है, और रूबी बस एक त्रुटि उठाती है जब आप ऐसा करते हैं। इसलिए 1 ++ को संभालना मुश्किल नहीं है। संभवत: उस प्रकार के सिंटैक्टिक चीनी के साथ सामना करने के लिए पार्सर की आवश्यकता अवांछनीय है।
स्टीव मिडग्ली

28

एक कारण यह है कि अब तक प्रत्येक असाइनमेंट ऑपरेटर (यानी एक ऑपरेटर जो एक चर को बदलता है) में एक =है। यदि आप जोड़ते हैं ++और --अब ऐसा नहीं है।

एक अन्य कारण है के व्यवहार कि ++और --अक्सर भ्रमित लोग। बिंदु में मामला: i++आपके उदाहरण में वापसी मूल्य वास्तव में 1 होगा, न कि 2 ( iहालांकि, का नया मूल्य 2 होगा, हालांकि)।


4
अब तक किसी भी अन्य कारण से अधिक, तर्कसंगत है कि "सभी असाइनमेंट्स =उनमें हैं" समझ में आता है। मैं सम्मान की तरह है कि स्थिरता के लिए एक उग्र पालन के रूप में कर सकते हैं।
एंडी_ वुल्फ

इस बारे में क्या: a.capitalize! (निहित काम)
लुइस सोरेस

1
@ लुइस्सारेस a.capitalize!पुन: असाइन नहीं करता है a, यह उस स्ट्रिंग को म्यूट करेगा जो aसंदर्भित करता है। एक ही स्ट्रिंग के अन्य संदर्भ प्रभावित होंगे और यदि आप a.object_idकॉल करने से पहले और बाद में करते हैं capitalize, तो आपको एक ही परिणाम प्राप्त होगा (यदि आप इसके a = a.capitalizeबजाय करते हैं तो इनमें से कोई भी सत्य नहीं होगा)।
sepp2k

1
@ LuíSSares जैसा कि मैंने कहा, a.capitalize!एक ही स्ट्रिंग के अन्य संदर्भों को प्रभावित करेगा। यह बहुत व्यावहारिक अंतर है। उदाहरण के लिए यदि आपके पास है def yell_at(name) name.capitalize!; puts "HEY, #{name}!" endऔर आप इसे इस तरह कहते हैं: अब my_name = "luis"; yell_at(my_name)का मूल्य my_nameहोगा "LUIS", जबकि यह अप्रभावित होगा यदि आपने उपयोग किया था capitalizeऔर एक असाइनमेंट।
sepp2k

1
वाह। यह डरावना है ... यह जानकर कि जावा में तार अपरिवर्तनीय हैं .. लेकिन शक्ति के साथ जिम्मेदारी आती है। स्पष्टीकरण के लिए धन्यवाद।
लुइस सोरेस

25

यह OO भाषाओं में पारंपरिक नहीं है। वास्तव में, ++स्मालटाक में कोई भी नहीं है, जिस भाषा ने "ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग" शब्द गढ़ा है (और रूबी भाषा सबसे अधिक प्रभावित है)। आपका क्या मतलब है कि यह सी में पारंपरिक है और भाषाओं में सी की बारीकी से नकल करना। रूबी के पास कुछ हद तक सी-सिंटैक्स है, लेकिन यह सी परंपराओं का पालन करने में सुस्त नहीं है।

क्योंकि यह रूबी में क्यों नहीं है: मात्स इसे नहीं चाहता था। वह वास्तव में परम कारण है।

स्मॉलटाक में ऐसी कोई भी चीज मौजूद नहीं होने का कारण यह है कि यह भाषा के ओवरराइडिंग दर्शन का एक हिस्सा है जो एक चर असाइन करना एक वस्तु को संदेश भेजने की तुलना में एक अलग तरह की चीज है - यह एक अलग स्तर पर है। इस सोच ने रूबी को डिजाइन करने में शायद मात्ज़ को प्रभावित किया।

इसे रूबी में शामिल करना असंभव नहीं होगा - आप आसानी से एक प्रीप्रोसेसर लिख सकते हैं जो सभी ++में बदल जाता है +=1। लेकिन जाहिर है कि Matz एक ऑपरेटर के विचार को पसंद नहीं करता था जो "छिपा हुआ असाइनमेंट" करता था। इसके अंदर छिपे हुए पूर्णांक संचालक के साथ एक ऑपरेटर होना भी थोड़ा अजीब लगता है। भाषा में कोई अन्य ऑपरेटर उस तरह से काम नहीं करता है।


1
मुझे नहीं लगता कि आप प्रीप्रोसेसर सुझाव काम करेंगे; (एक विशेषज्ञ नहीं) लेकिन मुझे लगता है कि i = 42, i ++ 42 वापस आ जाएगा जहां i + = 1 43 वापस आएगा। क्या मैं इसमें गलत हूं? तो उस मामले में आपका सुझाव i ++ का उपयोग करना होगा ++ के रूप में मैं सामान्य रूप से उपयोग किया जाता है जो कि बहुत बुरा इमो है और अच्छे से अधिक नुकसान पहुंचा सकता है।
अट्टुरसम्स

12

मुझे लगता है कि इसका एक और कारण है: ++रूबी सी और उसके प्रत्यक्ष उत्तराधिकारियों की तरह दूर से उपयोगी नहीं होगा।

इसका कारण, forकीवर्ड: C में आवश्यक होने के बावजूद, यह रूबी में अधिकांशतः शानदार है। रूबी में अधिकांश पुनरावृत्ति एन्यूमरेबल विधियों के माध्यम से की जाती है, जैसे कि eachऔर mapजब कुछ डेटा संरचना और Fixnum#timesविधि के माध्यम से पुनरावृत्ति होती है, जब आपको सटीक संख्या में लूप की आवश्यकता होती है।

दरअसल, जहां तक ​​मैंने देखा है, ज्यादातर समय +=1लोग सी-स्टाइल भाषाओं से रूबी के लिए नए सिरे से पलायन करते हैं।

संक्षेप में, यह वास्तव में संदेहास्पद है अगर तरीकों ++का --इस्तेमाल किया जाएगा।


1
यह सबसे अच्छा जवाब imho है। ++ का उपयोग अक्सर पुनरावृत्ति के लिए किया जाता है। रूबी इस प्रकार की पुनरावृत्ति को प्रोत्साहित नहीं करती है।
अतुरसम्स

3

मुझे लगता है कि मैट्स का तर्क उन्हें पसंद नहीं करने का तर्क है कि यह वास्तव में एक नए के साथ चर की जगह लेता है।

उदाहरण के लिए:

a = SomeClass.new
ago.go
  'हैलो'
समाप्त
# इस बिंदु पर, आप a.go कह सकते हैं
# लेकिन अगर आपने ए ++ किया है
# जिसका वास्तव में अर्थ = a + 1 है
# इसलिए अब आप a.go को कॉल नहीं कर सकते
# जैसा कि आपने अपना मूल खो दिया है

अब अगर कोई उसे समझा सकता है कि इसे सिर्फ #succ कहना चाहिए! या क्या नहीं, कि अधिक समझ में आता है, और समस्या से बचना होगा। आप इसे रूबी कोर पर सुझा सकते हैं।


9
"आप इसे रूबी कोर पर सुझा सकते हैं" ... आपके द्वारा अन्य सभी थ्रेड्स में तर्कों को पढ़ने और समझने के बाद, जहां इसे पिछली बार सुझाया गया था, और इससे पहले का समय, और उससे पहले का समय, और उससे पहले का समय, और इससे पहले का समय, और ... मैं रूबी समुदाय में बहुत लंबे समय से नहीं रहा हूं, लेकिन मेरे समय के दौरान, मुझे कम से कम बीस ऐसी चर्चाएं याद हैं।
जोर्ग डब्ल्यू मित्तग

3

आप .+स्व-वेतन वृद्धि ऑपरेटर को परिभाषित कर सकते हैं :

class Variable
  def initialize value = nil
    @value = value
  end
  attr_accessor :value
  def method_missing *args, &blk
    @value.send(*args, &blk)
  end
  def to_s
    @value.to_s
  end

  # pre-increment ".+" when x not present
  def +(x = nil)
    x ? @value + x : @value += 1
  end
  def -(x = nil)
    x ? @value - x : @value -= 1
  end
end

i = Variable.new 5
puts i                #=> 5

# normal use of +
puts i + 4            #=> 9
puts i                #=> 5

# incrementing
puts i.+              #=> 6
puts i                #=> 6

"वर्ग चर" पर अधिक जानकारी " क्लास वैरिएबल टू इंक्रीमेंट फिक्सनम ऑब्जेक्ट्स " में उपलब्ध है।


2

और डेविड ब्लैक के शब्दों में उनकी पुस्तक "द वेल-ग्राउंडेड रूबिस्ट":

रूबी में कुछ वस्तुओं को तत्काल मूल्यों के रूप में चर में संग्रहीत किया जाता है। इनमें पूर्णांक, प्रतीक (जो कि जैसे दिखते हैं: यह), और विशेष वस्तुएँ सत्य, असत्य और शून्य हैं। जब आप इनमें से किसी एक मान को एक चर (x = 1) में निर्दिष्ट करते हैं, तो चर इसके संदर्भ के बजाय स्वयं मूल्य रखता है। व्यावहारिक रूप से, यह कोई फर्क नहीं पड़ता (और इसे अक्सर इस पुस्तक में संदर्भों और संबंधित विषयों की चर्चा में, बार-बार वर्तनी के बजाय, निहित के रूप में छोड़ दिया जाएगा)। रूबी स्वचालित रूप से ऑब्जेक्ट संदर्भों की डीफ्रॉन्डिंग को संभालती है; किसी ऑब्जेक्ट को संदेश भेजने के लिए आपको कोई अतिरिक्त कार्य करने की आवश्यकता नहीं है, जिसमें किसी स्ट्रिंग के संदर्भ के रूप में, किसी ऑब्जेक्ट का विरोध करना, जिसमें तत्काल पूर्णांक मान शामिल है। लेकिन तात्कालिक मूल्य प्रतिनिधित्व नियम में कुछ दिलचस्प प्रभाव हैं, खासकर जब यह पूर्णांक की बात आती है। एक बात के लिए, किसी भी वस्तु को, जो एक तात्कालिक मूल्य के रूप में दर्शाया जाता है, हमेशा एक ही वस्तु होती है, चाहे वह कितने भी चर को सौंपे। केवल एक वस्तु 100 है, केवल एक वस्तु झूठी है, और इसी तरह। पूर्णांक-बाध्य चर की तात्कालिक, अनूठी प्रकृति रूबी के पूर्व और बाद के वेतन वृद्धि ऑपरेटरों की कमी के पीछे है - जो कहना है, आप रूबी में ऐसा नहीं कर सकते हैं: x = 1 x ++ # ऐसा कोई ऑपरेटर नहीं है, इसका कारण यह है कि x में 1 की तत्काल उपस्थिति, x ++ 1 ++ की तरह होगी, जिसका अर्थ है कि आप नंबर 1 को नंबर 2 में बदल रहे हैं - और इसका कोई मतलब नहीं है। कोई फर्क नहीं पड़ता कि कितने चर इसे सौंपा गया है। केवल एक वस्तु 100 है, केवल एक वस्तु झूठी है, और इसी तरह। पूर्णांक-बाध्य चर की तात्कालिक, अनूठी प्रकृति रूबी के पूर्व और बाद के वेतन वृद्धि ऑपरेटरों की कमी के पीछे है - जो कहना है, आप रूबी में ऐसा नहीं कर सकते हैं: x = 1 x ++ # ऐसा कोई ऑपरेटर नहीं है, इसका कारण यह है कि x में 1 की तत्काल उपस्थिति, x ++ 1 ++ की तरह होगी, जिसका अर्थ है कि आप नंबर 1 को नंबर 2 में बदल रहे हैं - और इसका कोई मतलब नहीं है। कोई फर्क नहीं पड़ता कि कितने चर इसे सौंपा गया है। केवल एक वस्तु 100 है, केवल एक वस्तु झूठी है, और इसी तरह। पूर्णांक-बाध्य चर की तात्कालिक, अनूठी प्रकृति रूबी के पूर्व और बाद के वेतन वृद्धि ऑपरेटरों की कमी के पीछे है - जो कहना है, आप रूबी में ऐसा नहीं कर सकते हैं: x = 1 x ++ # ऐसा कोई ऑपरेटर नहीं है, इसका कारण यह है कि x में 1 की तत्काल उपस्थिति, x ++ 1 ++ की तरह होगी, जिसका अर्थ है कि आप नंबर 1 को नंबर 2 में बदल रहे हैं - और इसका कोई मतलब नहीं है।


लेकिन आप कैसे आ सकते हैं "1.next" तब?
मैगने

1

फ़िक्नम या इंटेगर वर्ग में एक नई विधि जोड़कर इसे हासिल नहीं किया जा सकता है?

$ ruby -e 'numb=1;puts numb.next'

प्रतिफल २

"विध्वंसक" तरीकों से !संभव उपयोगकर्ताओं को चेतावनी देने के लिए संलग्न किया जा रहा है , इसलिए एक नई विधि को जोड़ना जो next!बहुत अनुरोध किया गया था यानी।

$ ruby -e 'numb=1; numb.next!; puts numb' 

2 रिटर्न (क्योंकि सुन्न बढ़ गया है)

बेशक, next!विधि को जांचना होगा कि ऑब्जेक्ट एक पूर्णांक चर था और वास्तविक संख्या नहीं थी, लेकिन यह उपलब्ध होना चाहिए।


1
Integer#nextपहले से मौजूद है (कम या ज्यादा), इसके Integer#succबजाय इसे ('उत्तराधिकारी') कहा जाता है । लेकिन Integer#next!(या Integer#succ!) बकवास होगा: याद रखें कि तरीके वस्तुओं पर काम करते हैं , न कि चर , इसलिए numb.next!बिल्कुल इसके बराबर होंगे 1.next!, जो यह कहना है कि यह 1 से 2 के बराबर होगा++यह मामूली रूप से बेहतर होगा क्योंकि यह एक असाइनमेंट के लिए सिंटैक्टिक शुगर हो सकता है, लेकिन व्यक्तिगत रूप से मैं वर्तमान सिंटैक्स पसंद करता हूं जहां सभी असाइनमेंट के साथ किया जाता है =
दार्शनिक

उपरोक्त टिप्पणी को पूरा करने के लिए: और Integer#predपूर्ववर्ती को पुनः प्राप्त करने के लिए।
योनी

-6

रूबी की विडंबना में सी-परिवार से इन ऑपरेटरों की जाँच करें और उन्हें अपने लिए परीक्षण करें:

x = 2    # x is 2
x += 2   # x is 4
x++      # x is now 8
++x      # x reverse to 4

3
यह स्पष्ट रूप से गलत है और काम नहीं करता है, जैसा (x++)कि रूबी में एक अमान्य बयान है।
22
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.