R में "=" और "<-" असाइनमेंट ऑपरेटरों के बीच अंतर क्या हैं?


712

असाइनमेंट ऑपरेटरों =और <-आर के बीच अंतर क्या हैं ?

मुझे पता है कि ऑपरेटर थोड़ा अलग हैं, जैसा कि इस उदाहरण से पता चलता है

x <- y <- 5
x = y = 5
x = y <- 5
x <- y = 5
# Error in (x <- y) = 5 : could not find function "<-<-"

लेकिन क्या यह एकमात्र अंतर है?


45
जैसा कि यहां बताया गया है कि <-प्रतीक की उत्पत्ति पुराने एपीएल कीबोर्ड से होती है जो वास्तव में <-उन पर एक ही कुंजी थी।
जोरन

जवाबों:


95

असाइनमेंट ऑपरेटरों =और <-आर के बीच अंतर क्या हैं ?

जैसा कि आपके उदाहरण से पता चलता है, =और <-थोड़ा अलग ऑपरेटर पूर्वता है (जो एक ही अभिव्यक्ति में मिश्रित होने पर मूल्यांकन के क्रम को निर्धारित करता है)। वास्तव में, ?SyntaxR में निम्न ऑपरेटर वरीयता तालिका देता है, उच्चतम से निम्नतम:

…
‘-> ->>’           rightwards assignment
‘<- <<-’           assignment (right to left)=’                assignment (right to left)

लेकिन क्या यह एकमात्र अंतर है?

चूंकि आप असाइनमेंट ऑपरेटरों के बारे में पूछ रहे थे : हां, यह एकमात्र अंतर है। हालांकि, आपको अन्यथा विश्वास करने के लिए माफ कर दिया जाएगा। यहां तक ?assignOpsकि दावों के आर प्रलेखन कि अधिक अंतर हैं:

ऑपरेटर <-का उपयोग कहीं भी किया जा सकता है, जबकि ऑपरेटर =को केवल शीर्ष स्तर पर अनुमति दी जाती है (जैसे, कमांड प्रॉम्प्ट पर टाइप की गई पूर्ण अभिव्यक्ति में) या अभिव्यक्तियों की एक ब्रेडेड सूची में सबएक्सप्रेस में से एक के रूप में।

चलो इस पर एक बिंदु भी ठीक नहीं डालते हैं: आर प्रलेखन (सूक्ष्म रूप से) गलत है [ 1 ] । यह दिखाना आसान है: हमें बस =ऑपरेटर के एक काउंटर-उदाहरण को खोजने की आवश्यकता है जो शीर्ष स्तर पर (ए) नहीं है, और न ही (बी) अभिव्यक्तियों की एक ब्रेडेड सूची (यानी {…; …}) में एक उपप्रकार है । - बिना और देरी के:

x
# Error: object 'x' not found
sum((x = 1), 2)
# [1] 3
x
# [1] 1

स्पष्ट रूप से हमने =प्रसंग (क) और (ख) के बाहर का उपयोग करते हुए एक असाइनमेंट किया है । तो, दशकों से एक कोर आर भाषा सुविधा का प्रलेखन गलत क्यों रहा है?

ऐसा इसलिए है क्योंकि R के सिंटैक्स में प्रतीक =के दो अलग-अलग अर्थ हैं जो नियमित रूप से भ्रमित होते हैं:

  1. पहला अर्थ असाइनमेंट ऑपरेटर के रूप में है । यह सब हमने अब तक के बारे में बात की है।
  2. दूसरा अर्थ एक ऑपरेटर नहीं है, बल्कि एक सिंटैक्स टोकन है जो एक फ़ंक्शन कॉल में तर्क नाम के संकेतों को पारित करता है। =ऑपरेटर के विपरीत , यह रनटाइम पर कोई कार्रवाई नहीं करता है, यह केवल एक अभिव्यक्ति को पार्स करने के तरीके को बदलता है।

चलो देखते हैं।

सामान्य रूप के किसी भी कोड के…

‹function_name›(‹argname› = ‹value›,)
‹function_name›(‹args›, ‹argname› = ‹value›,)

... =है यह: टोकन कि परिभाषित करता है नामित तर्क गुजर है नहीं असाइनमेंट ऑपरेटर। इसके अलावा, कुछ वाक्यात्मक संदर्भों में =पूरी तरह से निषिद्ध है:

if (‹var› = ‹value›) …
while (‹var› = ‹value›) …
for (‹var› = ‹value› in ‹value2›) …
for (‹var1› in ‹var2› = ‹value›) …

इनमें से कोई भी एक त्रुटि "अप्रत्याशित '=' को bla>" बढ़ाएगा।

किसी अन्य संदर्भ में, =असाइनमेंट ऑपरेटर कॉल को संदर्भित करता है। विशेष रूप से, केवल उपप्रकार के चारों ओर कोष्ठक लगाने से उपरोक्त (क) में से कोई भी वैध हो जाता है, और (ख) एक काम हो जाता है । उदाहरण के लिए, निम्नलिखित कार्य करता है:

median((x = 1 : 10))

लेकिन:

if (! (nf = length(from))) return()

अब आप इस बात पर आपत्ति कर सकते हैं कि ऐसा कोड अत्याचारपूर्ण है (और आप सही हो सकते हैं)। लेकिन मैंने इस कोड को base::file.copyफ़ंक्शन से बदल दिया ( <-साथ में)= ) - यह कोर आर कोडबेस में बहुत अधिक व्यापक पैटर्न है।

जॉन चैंबर्स द्वारा मूल स्पष्टीकरण , जो R प्रलेखन शायद पर आधारित है, वास्तव में सही ढंग इस बताते हैं:

[ =असाइनमेंट है] व्याकरण में केवल दो स्थानों पर अनुमति है: शीर्ष स्तर पर (एक पूर्ण कार्यक्रम या उपयोगकर्ता-टाइप की गई अभिव्यक्ति के रूप में); और जब आसपास के तार्किक ढांचे से, ब्रेसिज़ या कोष्ठक की एक अतिरिक्त जोड़ी से अलग किया जाता है।


एक स्वीकारोक्ति: मैंने पहले झूठ बोला था। वहाँ है के बीच एक अतिरिक्त अंतर =और <-ऑपरेटरों: वे अलग कार्यों कहते हैं। डिफ़ॉल्ट रूप से ये फ़ंक्शन समान कार्य करते हैं लेकिन व्यवहार को बदलने के लिए आप दोनों को अलग-अलग ओवरराइड कर सकते हैं। इसके विपरीत, <-और ->(बाएं से दाएं असाइनमेंट), हालांकि वाक्यात्मक रूप से अलग, हमेशा एक ही फ़ंक्शन को कॉल करते हैं। एक को ओवरराइड करने से दूसरा ओवरराइड भी करता है। यह जानना शायद ही व्यावहारिक है लेकिन इसका उपयोग कुछ मजेदार शेंनिगों के लिए किया जा सकता है


1
R की doc में पूर्ववर्तीता, और त्रुटियों के बारे में, पूर्ववर्तीता ?वास्तव में सही है बीच में =और <-, जिसके महत्वपूर्ण परिणाम हैं जब ओवरराइडिंग ? , और वस्तुतः अन्यथा कोई भी नहीं।
मूडी_मडस्किपर

@Moody_Mudskipper जो विचित्र है! आप सही होने लगते हैं, लेकिन के अनुसार स्रोत कोड ( main/gram.y), के पूर्वता ?सही ढंग से दस्तावेज, और दोनों की तुलना में कम है =और <-
कोनराड रुडोल्फ

मैं सी नहीं बोलता हूं, लेकिन मुझे लगता है कि =पार्स ट्री बनने से पहले एक विशेष उपचार मिलता है। शायद फ़ंक्शन तर्कों से संबंधित है, यह समझ में आता है कि foo(x = a ? b)हम =बाकी अभिव्यक्ति को पार्स करने से पहले देखेंगे ।
मूडी_मडस्किपर


2
@Moody_Mudskipper FWIW यह अंत में 4.0.0 में तय किया गया है।
कोनराड रुडोल्फ

661

जब आप फ़ंक्शन फ़ंक्शन कॉल में तर्क मान सेट करने के लिए उनका उपयोग करते हैं, तो असाइनमेंट ऑपरेटर्स का अंतर स्पष्ट होता है। उदाहरण के लिए:

median(x = 1:10)
x   
## Error: object 'x' not found

इस मामले में, xफ़ंक्शन के दायरे में घोषित किया जाता है, इसलिए यह उपयोगकर्ता कार्यक्षेत्र में मौजूद नहीं है।

median(x <- 1:10)
x    
## [1]  1  2  3  4  5  6  7  8  9 10

इस मामले xमें, उपयोगकर्ता कार्यक्षेत्र में घोषित किया जाता है, इसलिए आप फ़ंक्शन कॉल पूरा होने के बाद इसका उपयोग कर सकते हैं।


<-एस-प्लस के पुराने संस्करणों के साथ संगतता के लिए आर फ़ंक्शन (फ़ंक्शन हस्ताक्षरों के अलावा) के लिए उपयोग करने के लिए आर समुदाय के बीच एक सामान्य प्राथमिकता है । ध्यान दें कि रिक्त स्थान जैसी स्थितियों को स्पष्ट करने में मदद करते हैं

x<-3
# Does this mean assignment?
x <- 3
# Or less than?
x < -3

<-टाइप करने में आसान बनाने के लिए अधिकांश R IDE में कीबोर्ड शॉर्टकट हैं । Ctrl+ =वास्तुकार में, Alt+ -RStudio में ( Option+ -MacOS के तहत), Shift+ -Emacs + ईएसएस में (अंडरस्कोर)।


आप लिख पसंद करते हैं =करने के लिए <-, लेकिन सार्वजनिक रूप से जारी कोड के लिए और अधिक सामान्य काम प्रतीक (उदाहरण के लिए, क्रैन पर) का उपयोग करना चाहते हैं, तो आप में से एक का उपयोग कर सकते tidy_*में कार्य formatRपैकेज स्वचालित रूप से बदलने के लिए =के साथ <-

library(formatR)
tidy_source(text = "x=1:5", arrow = TRUE)
## x <- 1:5

प्रश्न का उत्तर " x <- y = 5त्रुटि क्यों फेंकता है लेकिन नहीं x <- y <- 5?" यह "यह जादू के लिए नीचे है।" आर के सिंटैक्स में कई अस्पष्ट मामले होते हैं जिन्हें एक या दूसरे तरीके से हल करना होता है। पार्सर अभिव्यक्ति के बिट्स को अलग-अलग क्रम में हल करने का विकल्प चुनता है =या नहीं, इस पर निर्भर करता है<- इस्तेमाल किया गया था ।

यह समझने के लिए कि क्या हो रहा है, आपको यह जानना होगा कि असाइनमेंट चुपचाप दिए गए मान को लौटाता है। आप उदाहरण के लिए स्पष्ट रूप से मुद्रण द्वारा अधिक स्पष्ट रूप से देख सकते हैंprint(x <- 2 + 3)

दूसरे, यह स्पष्ट है कि यदि हम असाइनमेंट के लिए उपसर्ग संकेतन का उपयोग करते हैं। इसलिए

x <- 5
`<-`(x, 5)  #same thing

y = 5
`=`(y, 5)   #also the same thing

पार्सर के x <- y <- 5रूप में व्याख्या करता है

`<-`(x, `<-`(y, 5))

हम उम्मीद कर सकते हैं कि x <- y = 5तब होगा

`<-`(x, `=`(y, 5))

लेकिन वास्तव में इसकी व्याख्या की जाती है

`=`(`<-`(x, y), 5)

इसका कारण यह है कि मदद पृष्ठ पर दिखाए गए की =तुलना में कम पूर्वता है ।<-?Syntax


4
पैट्रिक बर्न्स द्वारा द आर इनफर्नो के अध्याय 8.2.26 में भी इसका उल्लेख किया गया है (मुझे नहीं, लेकिन फिर भी सिफारिश)
Uwe

3
हालांकि, के रूप median((x = 1:10))में एक ही प्रभाव है median(x <- 1:10)
फ्रांसेस्को नेपोलिटानो

2
मैं वास्तव में उन्हें शॉर्टकट नहीं मानता, किसी भी स्थिति में आप समान कुंजी दबाते हैं
yosemite_k

5
मुझे बस एहसास हुआ कि आपकी व्याख्या किस तरह से की x <- x = 5जाती है, यह थोड़ा गलत है: वास्तव में, आर इसकी व्याख्या करता है ​`<-<-`(x, y = 5, value = 5)(जो खुद कमोबेश बराबर है tmp <- x; x <- `<-<-`(tmp, y = 5, value = 5))। ओह!
कोनराड रुडोल्फ

4
... और मुझे अभी पता चला है कि इस उत्तर का पहला भाग गलत है और दुर्भाग्य से, काफी भ्रामक है क्योंकि यह एक आम गलत धारणा को बनाए रखता है : जिस तरह से आप =फ़ंक्शन कॉल में उपयोग करते हैं वह असाइनमेंट नहीं करता है , और असाइनमेंट ऑपरेटर नहीं है। यह एक पूरी तरह से अलग आर अभिव्यक्ति है, जो सिर्फ उसी चरित्र का उपयोग करने के लिए होता है। इसके अलावा, आप जो कोड दिखाते हैं वह xफ़ंक्शन के दायरे में "घोषित" नहीं करता है। समारोह घोषणा प्रदर्शन घोषणा कहा। फ़ंक्शन कॉल नहीं करता है (यह नामित ...तर्क के साथ थोड़ा अधिक जटिल हो जाता है )।
कोनराड रुडोल्फ

103

Google की R शैली मार्गदर्शिका असाइनमेंट के लिए "=" को प्रतिबंधित करके समस्या को सरल बनाती है। बुरा विकल्प नहीं है।

https://google.github.io/styleguide/Rguide.xml

आर मैनुअल सभी 5 असाइनमेंट ऑपरेटरों पर अच्छा विस्तार से जाता है।

http://stat.ethz.ch/R-manual/R-patched/library/base/html/assignOps.html


133
x<-yकब x < -y, किसके द्वारा आकस्मिक असाइनमेंट के नकारात्मक पक्ष ने मुझे इतना पसंद किया कि मैं व्यक्तिगत रूप से पसंद करता हूं =। आपका कोड होना व्हाट्सएप पर निर्भर करता है कि मौजूद होना मुझे अच्छा नहीं लगता। शैली सलाह के रूप में रिक्ति का सुझाव देना ठीक है लेकिन आपके कोड के लिए अलग-अलग तरीके से चलना है या नहीं? क्या होगा यदि आप अपने कोड को सुधारते हैं, या खोज और प्रतिस्थापन का उपयोग करते हैं, तो व्हाट्सएप कभी-कभी गायब हो सकता है और कोड गड़बड़ा जाता है। यह एक समस्या नहीं है =। IIUC, =" <- " की आवश्यकता के बराबर है ; अर्थात्, एक स्थान सहित 3 वर्ण, केवल " <-" नहीं।
मैट डाउल

12
ध्यान दें कि किसी भी गैर-0 को TRUEआर। द्वारा माना जाता है। इसलिए यदि आप परीक्षण करना चाहते हैं यदि xइससे कम है -y, तो आप लिख सकते हैं if (x<-y)जो चेतावनी या त्रुटि नहीं देगा, और ठीक काम करने के लिए प्रकट होगा। हालांकि, यह तभी होगा FALSEजब y=0
मैट डोले

4
यदि आप निषेध करते हैं =और उपयोग करते हैं <- तो यह तर्क देना कठिन है कि अतिरिक्त कदम की grep "[^<]<-[^ ]" *.Rआवश्यकता नहीं है। =इस तरह की जरूरत नहीं है grep
मैट डाउल

34
<-यदि आप उपयोग कर सकते हैं, तो आपकी आंखों और उंगली को क्यों चोट लगी है =? 99.99% समय =में ठीक है। <<-हालांकि कभी-कभी आपको इसकी आवश्यकता होती है, जो एक अलग इतिहास है।
फर्नांडो

10
<- पर ध्यान केंद्रित शायद + = और - = की कमी के लंगड़ा कारणों में से एक है।
क्रिस

37

x = y = 5के बराबर है x = (y = 5), क्योंकि असाइनमेंट ऑपरेटर "समूह" को दाएं से बाएं, जो काम करता है। अर्थ: yसंख्या 5 से , 5 को असाइन करें ; और फिर उस 5 को असाइन करें x

यह वही नहीं है (x = y) = 5, जो काम नहीं करता है! अर्थ: के मान yको xछोड़कर, का मान निर्दिष्ट करेंy ; और फिर 5 को असाइन करें, उम्म ..., वास्तव में क्या?

जब आप विभिन्न प्रकार के असाइनमेंट ऑपरेटरों को मिलाते हैं, <-तो तंग को बांधता है =। तो x = y <- 5इसकी व्याख्या की जाती है x = (y <- 5), जो ऐसा मामला है जो समझ में आता है।

दुर्भाग्य से, के x <- y = 5रूप में व्याख्या की है (x <- y) = 5, जो मामला है कि काम नहीं करता है!

देखें ?Syntaxऔर ?assignOpsपूर्ववर्ती (बाध्यकारी) और समूहीकरण नियमों के लिए।


हां, जैसा कि कोनराड रूडोल्फ का जवाब <- <<-है = , पूर्ववर्ती तालिका में ऊपर है , जिसका अर्थ है कि <-पहले बाहर निकाला जाएगा। तो, के x <- y = 5रूप में निष्पादित किया जाना चाहिए (x <- y) = 5
निक डोंग

1
@ निक दांग वास्तव में हाँ। सहायक रूप से, ऑपरेटर पूर्ववर्ती तालिका को असंगत रूप से प्रलेखित किया जाता है ? सिंटैक्स {बेस}
स्टीव पिचर्स

33

जॉन चैंबर्स के अनुसार, ऑपरेटर =को केवल "शीर्ष स्तर" पर अनुमति दी जाती है, जिसका अर्थ है कि इसे नियंत्रण संरचनाओं में अनुमति नहीं है if, जैसे निम्नलिखित प्रोग्रामिंग त्रुटि को अवैध बनाता है।

> if(x = 0) 1 else x
Error: syntax error

जैसा कि वह लिखते हैं, "नियंत्रण के भाव में [=] नए असाइनमेंट फॉर्म को छोड़ने से प्रोग्रामिंग त्रुटियों (जैसे ऊपर उदाहरण) से बचा जाता है जो अन्य एस असाइनमेंट की तुलना में समान ऑपरेटर के साथ अधिक संभावना रखते हैं।"

आप ऐसा करने का प्रबंधन कर सकते हैं यदि यह "ब्रेसिज़ या कोष्ठक की एक अतिरिक्त जोड़ी द्वारा" तार्किक संरचना के आसपास से अलग किया जाता है, तो if ((x = 0)) 1 else xयह काम करेगा।

Http://developer.r-project.org/equalAssign.html देखें


11
यह एक सामान्य बग है, x==0लगभग हमेशा इसके बजाय होता है।
हारून ने स्टैक ओवरफ्लो

14
आह, हाँ, मैंने अनदेखी की कि आपने "प्रोग्रामिंग त्रुटि" कहा। यह वास्तव में अच्छी खबर है कि यह एक त्रुटि का कारण बनता है। और x=0असाइनमेंट के रूप में पसंद करने का एक अच्छा कारण x<-0!
स्टीव पिचर्स

7
हां, यह अच्छा है कि यह एक त्रुटि का कारण बनता है, हालांकि मैं एक अलग सबक आकर्षित करता हूं कि क्या पसंद करना है; मैं =जितना संभव हो उतना कम उपयोग करने का विकल्प चुनता हूं =और ==ऐसा ही दिखता हूं ।
हारून ने

2
इस उदाहरण को जिस तरह से प्रस्तुत किया गया है वह मेरे लिए बहुत अजीब है। if(x = 0) 1 else xएक त्रुटि फेंकता है, मुझे एक बग को खोजने और सही करने में मदद करता है। if(x <- 1) 1 else xएक त्रुटि नहीं है और बहुत भ्रामक है।
ग्रेगर थॉमस

3
मेरा मतलब है, वास्तव में उपयोगी त्रुटि चेकर एक त्रुटि को वहां फेंक देगा और कहेगा "आपके पास बेकार कोड है जो हमेशा elseमूल्य वापस कर देगा , क्या आपका मतलब इसे इस तरह से लिखना है?", लेकिन, यह एक पाइप सपना हो सकता है ...
TylerH

26

ऑपरेटर <-और =उस वातावरण में असाइन होते हैं जिसमें उनका मूल्यांकन किया जाता है। ऑपरेटर <-का उपयोग कहीं भी किया जा सकता है, जबकि ऑपरेटर =को केवल शीर्ष स्तर पर अनुमति दी जाती है (जैसे, कमांड प्रॉम्प्ट में टाइप की गई पूर्ण अभिव्यक्ति में) या अभिव्यक्तियों की एक लट में सूची में सबएक्सप्रेस के रूप में।


8
मुझे लगता है कि अभिव्यक्ति के स्तर के बजाय "शीर्ष स्तर" का अर्थ बयान स्तर पर है। तो x <- 42अपने आप पर एक बयान है; में if (x <- 42) {}यह एक अभिव्यक्ति होगा, और मान्य नहीं है। स्पष्ट होने के लिए, इससे कोई लेना-देना नहीं है कि आप वैश्विक वातावरण में हैं या नहीं।
स्टीव पिचर्स

1
यह: "ऑपरेटर = केवल शीर्ष स्तर पर अनुमत है" एक व्यापक रूप से आयोजित गलतफहमी है और पूरी तरह से गलत है।
कोनराड रुडोल्फ

यह सच नहीं है - उदाहरण के लिए, यह काम करता है, भले ही असाइनमेंट पूर्ण अभिव्यक्ति नहीं है:1 + (x = 2)
पावेल मिनावे

1
KonradRudolph और PavelMinaev द्वारा टिप्पणियों को स्पष्ट करने के लिए, मुझे लगता है कि यह कहना बहुत मजबूत है कि यह पूरी तरह से गलत है, लेकिन एक अपवाद है, जो तब है जब इसे "तार्किक संरचना से अलग किया जाता है, ब्रेसिज़ द्वारा या कोष्ठक की एक अतिरिक्त जोड़ी।"
हारून ने स्टैक ओवरफ्लो

या में function() x = 1, repeat x = 1, if (TRUE) x = 1....
Moody_Mudskipper

6

यह उन दो ऑपरेटरों के बीच अंतर की समझ को भी जोड़ सकता है:

df <- data.frame(
      a = rnorm(10),
      b <- rnorm(10)
)

पहले तत्व के लिए आर ने मान और उचित नाम दिया है, जबकि दूसरे तत्व का नाम थोड़ा अजीब है।

str(df)
# 'data.frame': 10 obs. of  2 variables:
#  $ a             : num  0.6393 1.125 -1.2514 0.0729 -1.3292 ...
#  $ b....rnorm.10.: num  0.2485 0.0391 -1.6532 -0.3366 1.1951 ...

आर संस्करण 3.3.2 (2016-10-31); macOS सिएरा 10.12.1


6
क्या आप इस बारे में अधिक विस्तृत स्पष्टीकरण दे सकते हैं कि ऐसा क्यों होता है / यहाँ क्या हो रहा है? (संकेत: data.frameडेटा फ़्रेम में तत्व के नाम के रूप में प्रदान किए गए चर के नाम का उपयोग करने की कोशिश करता है)
बेन बोल्कर

बस सोचा, यह संभवतः एक बग हो सकता है? और यदि हां, तो मैं इसे कैसे और कहां से रिपोर्ट करूं?
डेनिस रसुलेव

7
यह एक बग नहीं है। मैंने अपनी टिप्पणी के उत्तर में संकेत देने की कोशिश की। तत्व का नाम सेट करते समय R, के बराबर का उपयोग करेगा make.names("b <- rnorm(10)")
बेन बोलकर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.