934 votes

Quelles sont les différences entre les opérateurs d'affectation "=" et "<-" dans R ?

Quelles sont les différences entre les opérateurs d'affectation = y <- en R ?

Je sais que les opérateurs sont légèrement différents, comme le montre cet exemple

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

Mais est-ce la seule différence ?

62 votes

Comme indiqué aquí les origines de la <- proviennent de vieux claviers APL qui avaient en fait un seul symbole <- sur eux.

784voto

Richie Cotton Points 35365

La différence entre opérateurs d'affectation est plus clair lorsque vous les utilisez pour définir la valeur d'un argument dans un appel de fonction. Par exemple :

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

Dans ce cas, x est déclarée dans la portée de la fonction, elle n'existe donc pas dans l'espace de travail de l'utilisateur.

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

Dans ce cas, x est déclaré dans l'espace de travail de l'utilisateur, de sorte que vous pouvez l'utiliser après l'appel de la fonction.


Il y a une préférence générale parmi la communauté R pour l'utilisation de <- pour l'affectation (autre que dans les signatures de fonctions) pour la compatibilité avec les (très) anciennes versions de S-Plus. Notez que les espaces aident à clarifier des situations comme

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

La plupart des IDE de R ont des raccourcis clavier pour rendre <- plus facile à taper. Ctrl + = en tant qu'architecte, Alt + - dans RStudio ( Option + - sous macOS), Shift + - (underscore) dans emacs+ESS.


Si vous préférez écrire = a <- mais que vous souhaitez utiliser le symbole d'affectation plus courant pour le code publié publiquement (sur CRAN, par exemple), vous pouvez utiliser l'un des symboles suivants tidy_* fonctions dans le formatR pour remplacer automatiquement = con <- .

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

La réponse à la question "Pourquoi x <- y = 5 lancer une erreur mais pas x <- y <- 5 ?" est "C'est dû à la magie contenue dans l'analyseur syntaxique". La syntaxe de R contient de nombreux cas ambigus qui doivent être résolus d'une manière ou d'une autre. L'analyseur syntaxique choisit de résoudre les bits de l'expression dans des ordres différents selon que = o <- a été utilisé.

Pour comprendre ce qui se passe, vous devez savoir que l'affectation renvoie silencieusement la valeur qui a été affectée. Vous pouvez voir cela plus clairement en imprimant explicitement, par exemple print(x <- 2 + 3) .

Deuxièmement, il est plus clair d'utiliser la notation préfixe pour l'affectation. Ainsi,

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

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

L'analyseur interprète x <- y <- 5 comme

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

On peut s'attendre à ce que x <- y = 5 serait alors

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

mais en fait, il est interprété comme

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

Cela s'explique par le fait que = a une priorité inférieure à celle de <- comme indiqué sur le ?Syntax page d'aide.

12 votes

Ceci est également mentionné dans le chapitre 8.2.26 de L'enfer du R par Patrick Burns (Pas moi mais une recommandation quand même)

3 votes

Cependant, median((x = 1:10)) a le même effet que median(x <- 1:10) .

3 votes

Je ne les considère pas vraiment comme des raccourcis, dans tous les cas vous appuyez sur le même nombre de touches

111voto

Nosredna Points 33670

Le guide de style R de Google simplifie la question en interdisant le "=" pour l'affectation. Ce n'est pas un mauvais choix.

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

Le manuel R donne de nombreux détails sur les 5 opérateurs d'affectation.

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

154 votes

L'inconvénient de l'affectation accidentelle par x<-y quand x < -y me contrarie tellement que je préfère personnellement = . Le fait que votre code dépende de la présence d'espaces blancs ne me semble pas bon. Il est acceptable de suggérer l'espacement comme conseil de style, mais que votre code s'exécute différemment qu'il y ait un espace ou non ? Et si vous reformatez votre code, ou si vous utilisez la fonction de recherche et de remplacement, l'espace blanc peut parfois disparaître et le code se dérégler. Ce n'est pas un problème avec = . IIUC, interdisant = équivaut à exiger " <- " ; c'est-à-dire 3 caractères incluant un espace, et pas seulement " <- ".

13 votes

Notez que tout non-0 est considéré comme TRUE par R. Donc si vous avez l'intention de tester si x est inférieur à -y vous pourriez écrire if (x<-y) qui n'émet pas d'avertissement ou d'erreur, et semble fonctionner correctement. Ce sera seulement FALSE quand y=0 mais

4 votes

Si vous interdisez = et utiliser <- alors il est difficile d'argumenter qu'une étape supplémentaire de grep "[^<]<-[^ ]" *.R n'est pas nécessaire. = n'a pas besoin d'un tel grep .

48voto

Steve Pitchers Points 584

x = y = 5 est équivalent à x = (y = 5) car les opérateurs d'affectation "regroupent" de droite à gauche, ce qui fonctionne. Signification : assigner 5 à y en laissant le nombre 5 ; et ensuite affecter ce 5 à x .

Ce n'est pas la même chose que (x = y) = 5 ce qui ne fonctionne pas ! Signification : assigner la valeur de y a x en laissant la valeur de y ... et ensuite assigner 5 à, humm..., quoi exactement ?

Lorsque vous mélangez les différents types d'opérateurs d'affectation, <- se lie plus étroitement que = . Donc x = y <- 5 est interprété comme x = (y <- 5) ce qui est le cas qui a du sens.

Malheureusement, x <- y = 5 est interprété comme (x <- y) = 5 ce qui est le cas qui ne fonctionne pas !

Voir ?Syntax y ?assignOps pour les règles de précédence (liaison) et de regroupement.

0 votes

Oui, comme Konrad Rudolph La réponse de l'auteur dit <- <<- est au-dessus de = dans le tableau de précédence, ce qui signifie <- sera examiné en premier. Donc, x <- y = 5 doit être exécuté comme (x <- y) = 5 .

1 votes

Nick Dong Oui, en effet. Heureusement, la table de précédence des opérateurs est documentée sans ambiguïté dans ?syntaxe {base} .

38voto

Aaron Points 15093

Selon John Chambers, l'opérateur = n'est autorisé qu'au "niveau supérieur", ce qui signifie qu'il n'est pas autorisé dans les structures de contrôle telles que if ce qui rend illégale l'erreur de programmation suivante.

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

Comme il l'écrit, "interdire la nouvelle forme d'affectation [=] dans les expressions de contrôle évite les erreurs de programmation (comme l'exemple ci-dessus) qui sont plus probables avec l'opérateur égal qu'avec les autres affectations S."

Vous pouvez y parvenir s'il est "isolé de la structure logique environnante, par des accolades ou une paire de parenthèses supplémentaire", donc if ((x = 0)) 1 else x fonctionnerait.

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

0 votes

Que voulez-vous que fasse cette ligne ? C'est sûrement l'équivalent de x = 0 ?

14 votes

C'est un bug commun, x==0 est presque toujours utilisé à la place.

16 votes

Ah, oui, j'avais oublié que vous aviez dit "erreur de programmation". C'est en fait une bonne nouvelle que cela provoque une erreur. Et une bonne raison de préférer x=0 en tant qu'affectation sur x<-0 !

26voto

Haim Evgi Points 40786

Les opérateurs <- y = à l'environnement dans lequel ils sont évalués. L'opérateur <- peut être utilisé partout, alors que l'opérateur = n'est autorisé qu'au niveau supérieur (par exemple, dans l'expression complète tapée à l'invite de commande) ou comme l'une des sous-expressions d'une liste d'expressions entre crochets.

11 votes

Je pense que "niveau supérieur" signifie au niveau de la déclaration, plutôt qu'au niveau de l'expression. Donc x <- 42 est en soi une déclaration ; dans if (x <- 42) {} ce serait une expression, et elle n'est pas valide. Pour être clair, cela n'a rien à voir avec le fait que vous soyez dans l'environnement global ou non.

1 votes

Ceci : "l'opérateur = n'est autorisé qu'au niveau supérieur" est un malentendu largement répandu et complètement faux.

0 votes

Ce n'est pas vrai - par exemple, ceci fonctionne, même si l'affectation n'est pas une expression complète : 1 + (x = 2)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X