R:在C++/C#/Java中,+=(加等于)和++(自增)相当于吗?

206

R语言中是否有像C++、C#等其他编程语言中的+=(加上等于)或者++(自增)这样的概念?


15
不,使用 x += 1x++ 的方式不行 - x = x + 1 是有效的。 - Joshua Dawson
10个回答

148

73

按照@GregaKešpret的方法,您可以创建一个中缀运算符:

`%+=%` = function(e1,e2) eval.parent(substitute(e1 <- e1 + e2))
x = 1
x %+=% 2 ; x

12
(+1),但是需要警告一下。输入 x = %+=% y/2 会返回 x = (x + y)/2。加上括号,即 x = %+=% (y/2) 就可以解决这个问题了。 - knrumsey
@knrumsey 为什么呢?我本来以为除法会是一个更高优先级的运算符。 - David Kelley
1
@DavidKelley 不确定。我和你一样。我曾经在一个项目中遇到过这个问题,花了我一个小时才找到问题所在。 - knrumsey
3
记住你正在运行一个函数,而不是做加法。函数具有最高的优先级,因此如果没有括号,它会将y解析为函数输入,并将除法作为链中下一步。括号将(y/2)操作提升到链的顶部。 - Justin

37

R语言没有类似于C中的自增运算符++的概念。然而,你可以轻松地自己实现它,例如:

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

在那种情况下,您需要调用

x <- 10
inc(x)

然而,它引入了函数调用的开销,因此比自己键入 x <- x + 1 的速度。如果我没有错,增量运算符 的引入是为了让编译器更容易将代码直接转换为机器语言指令。


3
这个函数不能像后自增符号++一样返回值然后再进行增加。它更类似于+=或前自增符号++。 - Megatron
1
错误!增量不是为了让编译器的工作更容易而引入的。INC指令主要是为了实现计数器而在处理器中引入的(参见英特尔软件开发手册)。我会更新答案。 - banan3'14

26

R并没有这些操作,因为R中的大多数对象都是不可变的。它们不会改变。通常情况下,当你看起来在修改一个对象时,实际上你是在修改一个副本。

R语言没有提供这些操作,因为它内部的大部分对象是不可变的,也就是说它们的值一旦被赋予就无法再次修改。因此,在对某个对象进行所谓的“修改”时,实际上是创建了一个新的拷贝并进行了修改,而原始对象仍然保持不变。

22
虽然不可变性是对象的一个重要/理想属性(即减少错误),但我认为不可变性与+=问题无关。在其他语言中,+=可以应用于不可变类型(如 .net 中的字符串)。该操作只是创建一个新对象并将给定变量分配给该新对象。保持不可变性并更新变量。 - Suraj
5
好的观点。然而,不可变性确实使这种操作不太自然。 - hadley

15

增加和减少10。

require(Hmisc)
inc(x) <- 10 

dec(x) <- 10

9
似乎自Hmisc 4.1.0版本起,这些功能已被删除。 - llasram
10
@llasram看那个符号,我不能责怪任何人。 - bers

9

7
我们可以重写 +。如果使用一元的+,并且它的参数本身是一个一元的+调用,则增加调用环境中相关对象的值。
`+` <- 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

其他操作不会改变:

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

我不太能推荐这样做,因为您正在处理被优化的基元类型。


我喜欢这个答案。但是++1 ==>“1 <- 1 + 1的错误:无效(do_set)左侧赋值”! - Masoud
谢谢,我重新修改了答案,现在++1返回1。 - moodymudskipper
我认为++1应该返回2! - Masoud
我认为不是这样的,“++”是在原地递增一个对象,它只适用于符号,而“1”不是符号,我无法改变“1”的值,所以会回退到“+”的默认行为。 - moodymudskipper

1

我们也可以使用inplace

library(inplace)
x <- 1
x %+<-% 2

0

如果你想在数组中使用 i++ 来增加索引,可以尝试使用 i <- i + 1,例如:

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

但是这里的<-不能被替换为=,因为它不会更新索引。

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

由于在编程中,=<-并不总是等价的,正如在?`<-`中所说。


0

这里有一种更简单的方法来增加一个变量。

inc = 1

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

您将会得到以下结果

[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"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接