R: + = (mais iguais) e ++ (mais mais) equivalente de c ++ / c # / java, etc.?

146

R tem um conceito de +=(mais iguais) ou ++(mais mais) como c ++ / c # / outros têm?

SFun28
fonte
8
Não, para fazer x += 1ou x++- x = x + 1funciona.
Joshua Dawson

Respostas:

64

Seguindo @ GregaKešpret, você pode criar um operador de infix:

`%+=%` = function(e1,e2) eval.parent(substitute(e1 <- e1 + e2))
x = 1
x %+=% 2 ; x
baptiste
fonte
6
(+1), mas uma palavra de aviso. Digitando x = %+=% y/2retorna x = (x + y)/2. Adicionar parênteses, ou seja, x = %+=% (y/2)resolve o problema.
knrumsey
@knrumsey Por que isso? Eu imaginaria que a divisão seria um operador de precedência mais alta.
David Kelley
@DavidKelley Não tenho certeza. Eu estou com você lá. Encontrei este problema trabalhando em um projeto uma vez e levei uma hora para encontrar o problema.
knrumsey
Lembre-se de que você está executando uma função, não fazendo uma adição. As funções têm a precedência mais alta; portanto, sem parênteses, ele analisa y como entrada da função, com a divisão sendo o próximo passo na cadeia. Os parênteses elevam a operação (y / 2) para o topo da cadeia.
Justin
33

R não tem um conceito de increment operator(como por exemplo ++ em C). No entanto, não é difícil implementar você mesmo, por exemplo:

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

Nesse caso, você chamaria

x <- 10
inc(x)

No entanto, ele introduz despesas gerais de chamada de função, por isso é mais lento do que digitar x <- x + 1você mesmo. Se não me engano, increment operatorfoi introduzido para facilitar o trabalho do compilador, pois ele poderia converter o código diretamente nessas instruções de linguagem de máquina.

Grega Kešpret
fonte
3
Esta função não pode retornar o valor e incrementar como um pós-incremento ++. É mais parecido com + = ou pré-incremento ++.
Megatron
Errado! A incremento não foi introduzida para facilitar o trabalho do compilador. INCAs instruções foram introduzidas nos processadores principalmente para a implementação de contadores (consulte o Intel Software Developer's Manual). Eu atualizarei a resposta.
precisa saber é o seguinte
19

R não possui essas operações porque (a maioria) dos objetos em R são imutáveis. Eles não mudam. Normalmente, quando parece que você está modificando um objeto, na verdade está modificando uma cópia.

Hadley
fonte
18
Embora a imutabilidade seja uma propriedade ótima / desejável para objetos (leia-se: menos bugs), não acho que a imutabilidade esteja relacionada à questão + =. Em outros idiomas, + = pode ser aplicado a tipos imutáveis ​​(como strings em .net). A operação simplesmente cria um novo objeto e atribui a variável fornecida a esse novo objeto. A imutabilidade é mantida e a variável é atualizada.
SFun28
4
Bom ponto. A imutabilidade certamente torna esse tipo de operação menos natural, no entanto.
Hadley
15

Incrementar e diminuir em 10.

require(Hmisc)
inc(x) <- 10 

dec(x) <- 10
Andarilho
fonte
7
Essas funções parecem ter sido removidas Hmiscda versão 4.1.0.
Llasram
@llasram olhando para essa notação, não posso culpar ninguém.
bers
3

Nós podemos substituir +. Se unário +for usado e seu argumento for uma +chamada unária , aumente a variável relevante no ambiente de chamada.

`+` <- 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

outras operações não mudam:

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

Não faça isso, pois você diminuirá tudo. Ou faça-o em outro ambiente e verifique se você não possui grandes loops nessas instruções.

Você também pode fazer isso:

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

Existe outra maneira de fazer isso, que eu acho muito fácil, talvez possa ser de alguma ajuda

Eu uso <<-para essa situação Os operadores <<-atribuem o valor ao ambiente pai

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

e você pode chamar assim

x <- 0
inc(x)
Thevandalyst
fonte