Quelles sont les différences entre les opérateurs d'affectation =
et <-
dans 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?
r
assignment-operator
r-faq
csgillespie
la source
la source
<-
symbole proviennent d'anciens claviers APL qui avaient en fait une seule<-
clé.Réponses:
Comme le montre votre exemple,
=
et<-
ont une priorité d'opérateur légèrement différente (qui détermine l'ordre d'évaluation lorsqu'ils sont mélangés dans la même expression). En fait,?Syntax
dans R donne la table de priorité d'opérateur suivante, du plus haut au plus bas:Mais est-ce la seule différence?
Puisque vous posiez des questions sur les opérateurs d'affectation : oui, c'est la seule différence. Cependant, vous seriez pardonné de croire le contraire. Même la documentation R
?assignOps
affirme qu'il y a plus de différences:Ne précisons pas trop: la documentation R est (subtilement) fausse [ 1 ] . C'est facile à montrer: il suffit de trouver un contre-exemple de l'
=
opérateur qui n'est pas (a) au niveau supérieur, ni (b) une sous-expression dans une liste d'expressions contreventée (ie{…; …}
). - Sans plus tarder:De toute évidence, nous avons effectué une affectation, en utilisant
=
, en dehors des contextes (a) et (b). Alors, pourquoi la documentation d'une fonctionnalité de base du langage R est-elle erronée depuis des décennies?C'est parce que dans la syntaxe de R, le symbole
=
a deux significations distinctes qui sont systématiquement confondues:=
opérateur, il n'exécute aucune action au moment de l'exécution, il modifie simplement la façon dont une expression est analysée.Voyons voir.
Dans n'importe quel morceau de code de la forme générale…
… Le
=
est le jeton qui définit le passage d'argument nommé: ce n'est pas l'opérateur d'affectation. De plus,=
est totalement interdit dans certains contextes syntaxiques:N'importe lequel de ces éléments générera une erreur «inattendu '=' dans ‹bla›».
Dans tout autre contexte,
=
fait référence à l'appel d'opérateur d'affectation. En particulier, le simple fait de mettre des parenthèses autour de la sous-expression rend tout ce qui précède (a) valide et (b) une affectation . Par exemple, ce qui suit effectue l'affectation:Mais aussi:
Maintenant, vous pourriez objecter qu'un tel code est atroce (et vous avez peut-être raison). Mais j'ai pris ce code de la
base::file.copy
fonction (en le remplaçant<-
par=
) - c'est un modèle omniprésent dans une grande partie de la base de code R principale.L' explication originale de John Chambers , sur laquelle la documentation R est probablement basée, explique en fait cela correctement:
Une confession: j'ai menti plus tôt. Il existe une différence supplémentaire entre les opérateurs
=
et<-
: ils appellent des fonctions distinctes. Par défaut, ces fonctions font la même chose mais vous pouvez les remplacer séparément pour changer le comportement. En revanche,<-
et->
(affectation de gauche à droite), bien que syntaxiquement distincts, appellent toujours la même fonction. Remplacer l'un remplace également l'autre. Le savoir est rarement pratique, mais il peut être utilisé pour des manigances amusantes .la source
?
est en fait juste entre=
et<-
, ce qui a des conséquences importantes lors de la substitution?
, et pratiquement aucune autrement.main/gram.y
), la priorité de?
est correctement documentée et est inférieure aux deux=
et<-
.=
vous obtenez un traitement spécial avant que l'arbre d'analyse soit construit. Peut-être lié aux arguments de fonction, il est logique quefoo(x = a ? b)
nous recherchions=
avant d'analyser le reste de l'expression.La différence entre les opérateurs d'affectation est plus claire lorsque vous les utilisez pour définir une valeur d'argument dans un appel de fonction. Par exemple:
Dans ce cas,
x
est déclaré dans le cadre de la fonction, il n'existe donc pas dans l'espace de travail utilisateur.Dans ce cas,
x
est déclaré dans l'espace de travail utilisateur, vous pouvez donc l'utiliser une fois l'appel de fonction terminé.Il existe une préférence générale au sein de la communauté R pour l'utilisation
<-
pour l'affectation (autre que dans les signatures de fonction) pour la compatibilité avec les (très) anciennes versions de S-Plus. Notez que les espaces aident à clarifier des situations commeLa plupart des IDE R ont des raccourcis clavier pour
<-
faciliter la saisie. Ctrl+ =dans Architect, Alt+ -dans RStudio ( Option+ -sous macOS), Shift+ -(souligné) dans emacs + ESS.Si vous préférez écrire
=
dans<-
mais souhaitez utiliser le symbole d'affectation le plus courant pour le code publié publiquement (sur CRAN, par exemple), vous pouvez utiliser l'une destidy_*
fonctions duformatR
package pour le remplacer automatiquement=
par<-
.La réponse à la question "Pourquoi
x <- y = 5
jette une erreur mais pasx <- y <- 5
?" est "C'est dû à la magie contenue dans l'analyseur". La syntaxe de R contient de nombreux cas ambigus qui doivent être résolus d'une manière ou d'une autre. L'analyseur choisit de résoudre les bits de l'expression dans des ordres différents selon qu'il a été utilisé=
ou non<-
.Pour comprendre ce qui se passe, vous devez savoir que l'affectation renvoie silencieusement la valeur qui a été affectée. Vous pouvez le voir plus clairement en imprimant explicitement, par exemple
print(x <- 2 + 3)
.Deuxièmement, il est plus clair si nous utilisons la notation de préfixe pour l'affectation. Donc
L'analyseur interprète
x <- y <- 5
commeOn pourrait s'attendre à ce que ce
x <- y = 5
soit alorsmais en fait, il est interprété comme
Cela est dû au
=
fait que la priorité est inférieure à<-
, comme indiqué sur la?Syntax
page d'aide.la source
median((x = 1:10))
a le même effet quemedian(x <- 1:10)
.x <- x = 5
est interprété est légèrement erronée: en réalité, R l'interprète comme`<-<-`(x, y = 5, value = 5)
(ce qui lui-même est plus ou moins équivalent àtmp <- x; x <- `<-<-`(tmp, y = 5, value = 5)
). Oui!=
dans un appel de fonction n'effectue pas d'affectation et n'est pas un opérateur d'affectation. C'est une expression R analysée entièrement distincte, qui se trouve utiliser le même caractère. De plus, le code que vous montrez ne «déclare» pasx
dans le cadre de la fonction. La déclaration de fonction effectue ladite déclaration. L'appel de fonction ne fonctionne pas (il devient un peu plus compliqué avec des...
arguments nommés ).Le guide de style R de Google simplifie le problème en interdisant le "=" pour l'attribution. Pas un mauvais choix.
https://google.github.io/styleguide/Rguide.xml
Le manuel R rentre dans les moindres détails sur les 5 opérateurs d'affectation.
http://stat.ethz.ch/R-manual/R-patched/library/base/html/assignOps.html
la source
x<-y
quandx < -y
était voulu, 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. Vous pouvez suggérer l'espacement comme conseil de style, mais pour que votre code s'exécute différemment, qu'il y ait un espace ou non? Que se passe-t-il si vous reformatez votre code, ou utilisez la recherche et le remplacement, l'espace blanc peut parfois disparaître et le code tourne mal. Ce n'est pas un problème avec=
. IIUC, interdire=
équivaut à exiger "<-
"; c'est-à-dire, 3 caractères incluant un espace, pas seulement "<-
".TRUE
en compte par R. Donc, si vous avez l'intention de tester six
est inférieur à-y
, vous pouvez écrireif (x<-y)
ce qui ne vous avertira pas ou ne fera pas d'erreur et semblera fonctionner correctement. Ce ne sera queFALSE
quandy=0
, cependant.=
et utilisez,<-
il est difficile de prétendre qu'une étape supplémentaire degrep "[^<]<-[^ ]" *.R
n'est pas nécessaire.=
n'a pas besoin d'un telgrep
.<-
si vous pouvez l'utiliser=
? Dans 99,99% des temps,=
c'est bien. Parfois, vous avez besoin<<-
cependant, ce qui est une histoire différente.x = y = 5
est équivalent àx = (y = 5)
, car les opérateurs d'affectation "groupent" de droite à gauche, ce qui fonctionne. Signification: attribuer 5 ày
, en laissant le nombre 5; puis attribuez ce 5 àx
.Ce n'est pas la même chose que
(x = y) = 5
, qui ne fonctionne pas! Signification: attribuer la valeur dey
àx
, en laissant la valeur dey
; puis attribuer 5 à, euh ..., quoi exactement?Lorsque vous mélangez les différents types d'opérateurs d'affectation, les
<-
liaisons sont plus strictes que=
.x = y <- 5
Est donc interprété commex = (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
et?assignOps
pour les règles de priorité (liaison) et de regroupement.la source
<- <<-
au-dessus du=
tableau de priorité, ce qui signifie<-
qu'il sera exécuté en premier. Donc,x <- y = 5
devrait être exécuté comme(x <- y) = 5
.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ôleif
, ce qui rend l'erreur de programmation suivante illégale.Comme il l'écrit, «Interdire le nouveau formulaire 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 réussir à le faire s'il est "isolé de la structure logique environnante, par des accolades ou une paire de parenthèses supplémentaires", alors
if ((x = 0)) 1 else x
cela fonctionnerait.Voir http://developer.r-project.org/equalAssign.html
la source
x==0
c'est presque toujours à la place.x=0
comme mission plusx<-0
!=
le moins possible car=
et me==
ressemble tellement.if(x = 0) 1 else x
renvoie une erreur, m'aidant à trouver et à corriger un bogue.if(x <- 1) 1 else x
ne génère pas d'erreur et est très déroutant.else
valeur, vouliez-vous l'écrire de cette façon?", Mais, cela peut être un rêve de pipe ...Les opérateurs
<-
et=
affectent dans l'environnement dans lequel ils sont évalués. L'opérateur<-
peut être utilisé n'importe où, alors qu'il=
n'est autorisé qu'au niveau supérieur (par exemple, dans l'expression complète saisie à l'invite de commande) ou comme l'une des sous-expressions dans une liste d'expressions contreventée.la source
x <- 42
en soi, c'est une déclaration; enif (x <- 42) {}
elle serait une expression, et n'est pas valide. Pour être clair, cela n'a rien à voir avec le fait que vous soyez ou non dans l'environnement mondial.1 + (x = 2)
function() x = 1
,repeat x = 1
,if (TRUE) x = 1
....Cela peut également contribuer à la compréhension de la différence entre ces deux opérateurs:
Pour le premier élément, R a attribué des valeurs et un nom propre, tandis que le nom du deuxième élément semble un peu étrange.
R version 3.3.2 (2016-10-31); macOS Sierra 10.12.1
la source
data.frame
essaie d'utiliser le nom de la variable fournie comme nom de l'élément dans lemake.names("b <- rnorm(10)")
.