R: + = (plus égal) et ++ (plus plus) équivalent de c ++ / c # / java, etc.?

147

R a-t-il un concept de +=(plus égal) ou ++(plus plus) comme le font c ++ / c # / others?

SFun28
la source
8
Non, à faire x += 1ou x++- x = x + 1fonctionne.
Joshua Dawson

Réponses:

64

Après @ GregaKešpret, vous pouvez créer un opérateur d'infixe:

`%+=%` = function(e1,e2) eval.parent(substitute(e1 <- e1 + e2))
x = 1
x %+=% 2 ; x
baptiste
la source
6
(+1), mais un mot d'avertissement. La frappe x = %+=% y/2revient x = (x + y)/2. L'ajout de parenthèses, c'est-à-dire x = %+=% (y/2)résout le problème.
knrumsey
@knrumsey Pourquoi est-ce? J'aurais supposé que la division serait un opérateur de priorité plus élevée.
David Kelley
@DavidKelley Pas sûr. Je suis avec toi là-bas. J'ai rencontré ce problème en travaillant sur un projet une fois et il m'a fallu une heure pour trouver le problème.
knrumsey
N'oubliez pas que vous exécutez une fonction, pas une addition. Les fonctions ont la priorité la plus élevée, donc sans la parenthèse, elle analyse le y comme entrée de fonction, la division étant l'étape suivante dans la chaîne. La parenthèse élève l'opération (y / 2) en haut de la chaîne.
Justin
33

R n'a pas de concept de increment operator(comme par exemple ++ en C). Cependant, il n'est pas difficile d'en implémenter un vous-même, par exemple:

inc <- function(x)
{
 eval.parent(substitute(x <- x + 1))
}

Dans ce cas, vous appelleriez

x <- 10
inc(x)

Cependant, cela introduit une surcharge d'appel de fonction, donc c'est plus lent que de taper x <- x + 1vous-même. Si je ne me trompe pas, il a increment operatorété introduit pour faciliter le travail du compilateur, car il pourrait convertir directement le code en ces instructions en langage machine.

Grega Kešpret
la source
3
Cette fonction ne peut pas retourner la valeur puis incrémenter comme un postincrement ++. C'est plus similaire à + = ou preincrement ++.
Megatron
Faux! L'incrémentation n'a pas été introduite pour faciliter le travail du compilateur. INCL'instruction a été introduite dans les processeurs principalement pour l'implémentation des compteurs (cf. Manuel du développeur de logiciels Intel). Je mettrai à jour la réponse.
banan3'14
19

R n'a pas ces opérations car (la plupart) des objets dans R sont immuables. Ils ne changent pas. En règle générale, lorsqu'il semble que vous modifiez un objet, vous modifiez en fait une copie.

hadley
la source
18
Bien que l'immuabilité soit une propriété intéressante / souhaitable pour les objets (lire: moins de bogues), je ne pense pas que l'immutabilité soit liée à la question + =. Dans d'autres langages, + = peut être appliqué à des types immuables (comme des chaînes dans .net). L'opération crée simplement un nouvel objet et affecte la variable donnée à ce nouvel objet. L'immuabilité est maintenue et la variable est mise à jour.
SFun28
4
Bon point. Cependant, l'immuabilité rend certainement ce genre d'opération moins naturel.
hadley
15

Incrémenter et décrémenter de 10.

require(Hmisc)
inc(x) <- 10 

dec(x) <- 10
Vagabond
la source
7
Ces fonctions semblent avoir été supprimées depuis la Hmiscversion 4.1.0.
llasram
@llasram en regardant cette notation, je ne peux blâmer personne.
bers
3

Nous pouvons passer outre +. Si unaire +est utilisé et que son argument est lui-même un +appel unaire , incrémentez la variable appropriée dans l'environnement appelant.

`+` <- function(e1,e2){
    # if unary `+`, keep original behavior
    if(missing(e2)) {
      s_e1 <- substitute(e1)
      # if e1 (the argument of unary +) is itself an unary `+` operation
      if(length(s_e1) == 2 && 
         identical(s_e1[[1]], quote(`+`)) && 
         length(s_e1[[2]]) == 1){
        # increment value in parent environment
        eval.parent(substitute(e1 <- e1 + 1,list(e1 = s_e1[[2]])))
      # else unary `+` should just return it's input
      } else e1
    # if binary `+`, keep original behavior
    } else .Primitive("+")(e1,e2)
}

x <- 10
++x
x
# [1] 11

les autres opérations ne changent pas:

x + 2
# [1] 13
x ++ 2
# [1] 13
+x
# [1] 11
x
# [1] 11

Ne le faites pas car vous ralentirez tout. Ou faites-le dans un autre environnement et assurez-vous de ne pas avoir de grandes boucles sur ces instructions.

Vous pouvez également simplement faire ceci:

`++` <- function(x) eval.parent(substitute(x <-x +1))
a <- 1
`++`(a)
a
# [1] 2
Moody_Mudskipper
la source
-1

Il y a une autre façon de faire cela, que je trouve très facile, peut-être que cela pourrait vous aider

J'utilise <<-pour ces situations Les opérateurs <<-attribuent la valeur à l'environnement parent

inc <- function(x)
{
   x <<- x + 1
}

et vous pouvez l'appeler comme

x <- 0
inc(x)
Thevandalyst
la source