Wat zijn de verschillen tussen de toewijzingsoperatoren = en <- in R?

Wat zijn de verschillen tussen de toewijzingsoperatoren = en <- in R?

Ik weet dat operators iets anders zijn, zoals dit voorbeeld laat zien

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

Maar is dit het enige verschil?


Antwoord 1, autoriteit 100%

Wat zijn de verschillen tussen de toewijzingsoperatoren = en <- in R?

Zoals uw voorbeeld laat zien, hebben = en <- een iets andere operatorprioriteit (die de volgorde van evaluatie bepaalt wanneer ze in dezelfde uitdrukking worden gemengd). ?Syntax in R geeft de volgende operatorprioriteittabel, van hoog naar laag:

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

Maar is dit het enige verschil?

Sinds u vroeg naar de toewijzingsoperatoren: ja, dat is het enige verschil. Het zou je echter vergeven worden als je anders gelooft. Zelfs de R-documentatie van ?assignOps beweert dat er meer verschillen zijn:

De operator <- kan overal worden gebruikt,
terwijl de operator = alleen is toegestaan ​​op het hoogste niveau (bijv.
in de volledige uitdrukking getypt bij de opdrachtprompt) of als één
van de subuitdrukkingen in een lijst met uitdrukkingen tussen haakjes.

Laten we er niet al te veel op zeggen: de R-documentatie is verkeerd. Dit is eenvoudig aan te tonen: we hoeven alleen maar een tegenvoorbeeld te vinden van de operator = die niet (a) op het hoogste niveau is, noch (b) een subexpressie in een lijst met accolades met expressies (dwz {…; …}).  Zonder meer:

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

Het is duidelijk dat we een opdracht hebben uitgevoerd, met behulp van =, buiten de contexten (a) en (b). Dus waarom is de documentatie van een kernfunctie van R-taal al tientallen jaren verkeerd?

Het is omdat in de syntaxis van R het symbool = twee verschillende betekenissen heeft die routinematig door elkaar worden gehaald (zelfs door experts, ook in de hierboven aangehaalde documentatie):

  1. De eerste betekenis is als een toewijzingsoperator. Dit is alles waar we het tot nu toe over hebben gehad.
  2. De tweede betekenis is geen operator, maar eerder een syntaxistoken dat aangeeft dat named argument wordt doorgegeven in een functieaanroep. In tegenstelling tot de = operator voert het geen actie uit tijdens runtime, het verandert alleen de manier waarop een uitdrukking wordt geparseerd.

Dus hoe beslist R of een bepaald gebruik van = verwijst naar de operator of naar het doorgeven van genoemd argument? Eens kijken.

In elk stukje code van de algemene vorm 

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

 de = is het token dat het doorgeven van benoemde argumenten definieert: het is niet de toewijzingsoperator. Bovendien is = volledig verboden in sommige syntactische contexten:

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

Elk van deze zal een fout unexpected ‘=’ in bla veroorzaken.

In elke andere context verwijst = naar de oproep van de toewijzingsoperator. Met name het plaatsen van haakjes rond de subexpressie maakt elk van de bovenstaande (a) geldig, en (b) een toewijzing. De volgende voert bijvoorbeeld een opdracht uit:

median((x = 1 : 10))

Maar ook:

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

Nu zou je kunnen tegenwerpen dat een dergelijke code afschuwelijk is (en misschien heb je gelijk). Maar ik nam deze code van de functie base::file.copy (vervanging van <- door =) patroon in een groot deel van de kern R-codebase.

De originele uitleg door John Chambers, waarop de R-documentatie waarschijnlijk is gebaseerd , legt dit eigenlijk correct uit:

[= toewijzing is] toegestaan ​​op slechts twee plaatsen in de grammatica: op het hoogste niveau (als een volledig programma of door een gebruiker getypte uitdrukking); en wanneer geïsoleerd van de omringende logische structuur, door accolades of een extra paar haakjes.


Kortom, standaard doen de operators <- en = hetzelfde. Maar een van beide kan afzonderlijk worden overschreven om het gedrag ervan te veranderen. Daarentegen roepen <- en -> (toewijzing van links naar rechts), hoewel syntactisch verschillend, altijd de functie dezelfde aan. Het overschrijven van het ene heeft ook voorrang op het andere. Dit weten is zelden praktisch maar het kan voor sommigen worden gebruikt leuke grappen.


Antwoord 2, autoriteit 98%

Het verschil in toewijzingsoperators is duidelijker wanneer u ze gebruikt om een argumentwaarde in een functieaanroep. Bijvoorbeeld:

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

In dit geval wordt x gedeclareerd binnen het bereik van de functie, dus het bestaat niet in de gebruikerswerkruimte.

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

In dit geval wordt x gedeclareerd in de gebruikerswerkruimte, zodat u deze kunt gebruiken nadat de functieaanroep is voltooid.


Er is een algemene voorkeur onder de R-gemeenschap voor het gebruik van <- voor toewijzing (anders dan in functiehandtekeningen) voor compatibiliteit met (zeer) oude versies van S-Plus. Merk op dat de spaties helpen om situaties zoals

. te verduidelijken

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

De meeste R IDE’s hebben sneltoetsen om <- gemakkelijker te typen. Ctrl + = in Architect, Alt + - in RStudio (Optie + < kbd>– onder macOS), Shift + - (underscore) in emacs+ESS.


Als u liever = naar <- schrijft, maar het meer algemene toewijzingssymbool wilt gebruiken voor openbaar vrijgegeven code (bijvoorbeeld op CRAN), dan kunt u gebruik een van de tidy_*-functies in de formatR pakket om = automatisch te vervangen door <-.

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

Het antwoord op de vraag “Waarom geeft x <- y = 5 een fout, maar x <- y <- 5 niet?” is “Het komt door de magie in de parser”. De syntaxis van R bevat veel onduidelijke gevallen die op de een of andere manier moeten worden opgelost. De parser kiest ervoor om de bits van de uitdrukking in verschillende volgordes op te lossen, afhankelijk van of = of <- werd gebruikt.

Om te begrijpen wat er gebeurt, moet je weten dat de toewijzing stilzwijgend de toegewezen waarde retourneert. U kunt dat duidelijker zien door expliciet af te drukken, bijvoorbeeld print(x <- 2 + 3).

Ten tweede is het duidelijker als we prefixnotatie gebruiken voor toewijzing. Dus

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

De parser interpreteert x <- y <- 5 als

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

We zouden kunnen verwachten dat x <- y = 5 dan

zou zijn

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

maar eigenlijk wordt het geïnterpreteerd als

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

Dit komt omdat = een lagere prioriteit heeft dan <-, zoals te zien is op de ?Syntax helppagina.


Antwoord 3, autoriteit 57%

De R-stijlgids van Google vereenvoudigt het probleem door de ‘=” voor toewijzing te verbieden. Geen slechte keuze.

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

De R-handleiding gaat gedetailleerd in op alle 5 opdrachtoperators.

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


Antwoord 4, autoriteit 23%

x = y = 5 is gelijk aan x = (y = 5), omdat de toewijzingsoperatoren van rechts naar links “groeperen”, wat werkt. Betekenis: wijs 5 toe aan y, waarbij het cijfer 5 overblijft; en wijs die 5 vervolgens toe aan x.

Dit is niet hetzelfde als (x = y) = 5, wat niet werkt! Betekenis: wijs de waarde van y toe aan x, waarbij de waarde van y overblijft; en dan 5 toewijzen aan, euh…, wat precies?

Als je de verschillende soorten toewijzingsoperatoren door elkaar haalt, bindt <- strakker dan =. Dus x = y <- 5 wordt geïnterpreteerd als x = (y <- 5), wat logisch is.

Helaas wordt x <- y = 5 geïnterpreteerd als (x <- y) = 5, wat het geval is dat niet werkt!

Zie ?Syntax en ?assignOps voor de voorrangs- (bindings-) en groeperingsregels.


Antwoord 5, autoriteit 18%

Volgens John Chambers is de operator = alleen toegestaan ​​op “het hoogste niveau”, wat betekent dat het niet is toegestaan ​​in besturingsstructuren zoals if, waardoor het volgende ontstaat programmeerfout illegaal.

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

Zoals hij schrijft: “Als u de nieuwe toewijzingsvorm [=] in besturingsexpressies niet toestaat, worden programmeerfouten (zoals het bovenstaande voorbeeld) vermeden die waarschijnlijker zijn met de gelijke-operator dan met andere S-toewijzingen.”

Je kunt dit doen als het “geïsoleerd is van de omringende logische structuur, door accolades of een extra paar haakjes”, dus if ((x = 0)) 1 else x zou werken.

Zie http://developer.r-project.org/equalAssign.html


Antwoord 6, autoriteit 13%

De operators <- en = wijzen toe aan de omgeving waarin ze worden geëvalueerd. De operator <- kan overal worden gebruikt, terwijl de operator = alleen op het hoogste niveau is toegestaan ( bijv. in de volledige uitdrukking die bij de opdrachtprompt is getypt) of als een van de subuitdrukkingen in een lijst met uitdrukkingen tussen haakjes.


Antwoord 7, autoriteit 4%

Dit kan ook bijdragen aan het begrip van het verschil tussen deze twee operators:

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

Voor het eerste element heeft R waarden en eigennaam toegewezen, terwijl de naam van het tweede element er een beetje vreemd uitziet.

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 ...

R versie 3.3.2 (2016-10-31); macOS Sierra 10.12.1

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Other episodes