202

Does R have a concept of += (plus equals) or ++ (plus plus) as c++/c#/others do?

zx8754
  • 52,746
  • 12
  • 114
  • 209
Suraj
  • 35,905
  • 47
  • 139
  • 250

10 Answers10

145

No, it doesn't, see: R Language Definition: Operators

zx8754
  • 52,746
  • 12
  • 114
  • 209
Patrick Cuff
  • 28,540
  • 12
  • 67
  • 94
72

Following @GregaKešpret you can make an infix operator:

`%+=%` = function(e1,e2) eval.parent(substitute(e1 <- e1 + e2))
x = 1
x %+=% 2 ; x
baptiste
  • 75,767
  • 19
  • 198
  • 294
  • 12
    (+1), but a word of warning. Typing `x = %+=% y/2` returns `x = (x + y)/2`. Adding parenthesis, i.e. `x = %+=% (y/2)` solves the problem. – knrumsey Sep 21 '18 at 21:08
  • @knrumsey Why is that? I would've guessed division would be a higher precedence operator. – David Kelley Feb 17 '19 at 22:16
  • 1
    @DavidKelley Not sure. I'm with you there. I ran into this issue working on a project once and it took me an hour to find the issue. – knrumsey Feb 17 '19 at 22:38
  • 3
    Remember you're running a function, not doing an addition. Functions have the highest precedence so without the parenthesis it parses the y as the function input with the division being the next step down the chain. The parenthesis elevate the (y/2) operation to the top of the chain. – Justin Jun 10 '20 at 04:07
37

R doesn't have a concept of increment operator (as for example ++ in C). However, it is not difficult to implement one yourself, for example:

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

In that case you would call

x <- 10
inc(x)

However, it introduces function call overhead, so it's slower than typing x <- x + 1 yourself. If I'm not mistaken increment operator was introduced to make job for compiler easier, as it could convert the code to those machine language instructions directly.

Grega Kešpret
  • 11,827
  • 6
  • 39
  • 44
  • 3
    This function cannot return the value and then increment like a postincrement ++. It's more similar to += or preincrement ++. – Megatron Jul 10 '15 at 18:52
  • 1
    Wrong! Incrementation wasn't introduced to make the job of compiler easier. `INC` instruction was introduced **in processors** primarily for implementing counters (cf. Intel Software Developer's Manual). I will update the answer. – banan3'14 Nov 04 '18 at 22:50
25

R doesn't have these operations because (most) objects in R are immutable. They do not change. Typically, when it looks like you're modifying an object, you're actually modifying a copy.

hadley
  • 102,019
  • 32
  • 183
  • 245
  • 22
    While immutability is a great/desirable property for objects (read: less bugs) I don't think immutability relates to the += question. In other languages += can be applied to immutable types (like strings in .net). The operation simply creates a new object and assigns the given variable to that new object. Immutability is maintained and the variable is updated. – Suraj Apr 21 '11 at 13:35
  • 5
    Good point. Immutability certainly makes this sort of operation less natural, however. – hadley Apr 22 '11 at 03:20
15

Increment and decrement by 10.

require(Hmisc)
inc(x) <- 10 

dec(x) <- 10
Gavin Simpson
  • 170,508
  • 25
  • 396
  • 453
Wanderer
  • 1,583
  • 4
  • 20
  • 36
8

We released a package, roperators, to help with this kind of thing. You can read more about it here: https://happylittlescripts.blogspot.com/2018/09/make-your-r-code-nicer-with-roperators.html

install.packages('roperators')
require(roperators)

x <- 1:3
x %+=% 1; x
x %-=% 3; x
y <- c('a', 'b', 'c')
y %+=% 'text'; y
y %-=% 'text'; y

# etc
Benbob
  • 328
  • 2
  • 4
7

We can override +. If unary + is used and its argument is itself an unary + call, then increment the relevant object in the calling environment.

`+` <- function(e1,e2){
  # if binary `+`, keep original behavior
  if(!missing(e2)) return(base::`+`(e1, e2))
  
  # if inner call isn't unary `+` called on language object,
  # keep original behavior
  inner_call <- substitute(e1)
  inner_call_is_plus_on_lng <-
    length(inner_call) == 2 &&
    identical(inner_call[[1]], quote(`+`)) &&
    is.language(inner_call[[2]])
  if(!inner_call_is_plus_on_lng) return(base::`+`(e1))
  
  eval.parent(substitute(X <- X + 1, list(X = inner_call[[2]])))
}

x <- 10

++x
x
#> [1] 11

other operations don't change :

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

I can't really recommend it since you're messing with primitives which are optimised for a reason.

moodymudskipper
  • 46,417
  • 11
  • 121
  • 167
1

We can also use inplace

library(inplace)
x <- 1
x %+<-% 2
akrun
  • 874,273
  • 37
  • 540
  • 662
0

If you want to use i++ in an array to increment the index, you can try i <- i + 1, for example,

k = 0
a = 1:4
for (i in 1:4) 
    cat(a[k <- k + 1], " ")
# 1 2 3 4

but here <- can NOT be replaced with =, which does not update the index,

k = 0
a = 1:4
for (i in 1:4) 
    cat(a[k = k + 1], " ")
# 1 1 1 1

since = and <- are not always equivalent, as said in ?`<-`

ya wei
  • 77
  • 5
0

Here is a simpler approach to increment a variable.

inc = 1

for(i in 1:10){
    print(paste("Value of inc: ", inc))
    inc = sum(c(inc, 1))
}

You will get results as follows

[1] "Value of inc:  1"
[1] "Value of inc:  2"
[1] "Value of inc:  3"
[1] "Value of inc:  4"
[1] "Value of inc:  5"
[1] "Value of inc:  6"
[1] "Value of inc:  7"
[1] "Value of inc:  8"
[1] "Value of inc:  9"
[1] "Value of inc:  10"
Al-Mahi
  • 1
  • 1