参考:https://www.cnblogs.com/loca/p/4301344.html
主要还是这三兄弟:<-
, =
, <<-
1. = 和 <-
R语言中,<- 与 = 这两个赋值运算符最主要的区别在于两者的作用域不同。大家可以从下面的例子感受一下。
> rm(x) ## 如果变量 x 存在的话,删除此变量
> mean(x = 1:10)
[1] 5.5
> x
Error: object 'x' not found
在以上范例里,变量 x 是在函数的作用域里进行声明的,所以它只存在于此函数中,一旦运算完成便“消失”。
而如果是<-符号:
> mean(x <- 1:10)
[1] 5.5
> x
[1] 1 2 3 4 5 6 7 8 9 10
ps:至于R 使用<- 太麻烦怎么办,R 提供了快捷键 alt
+ -
输入。
2. <- 赋值成立条件
上述语句的处理是“将 1:10 赋值给 x , 然后计算 x 的均值。” 吗?在某些语言里,计算机的确是如此处理的,比如说 C 。
> a <- 1
> f <- function(a) return(TRUE)
> f <- f(a <- a + 1); a
[1] TRUE
[1] 1
可见,在R 中并非如此。a 的值并没有改变,在 R 中,在参数中进行赋值的变量只有函数内容调用其时才会发生改变,这其实也是R “懒惰求值”的特性,只有用到某个形式变量的值才求出其对应实参的值。只有使用到a 时,才会求出a 实参结果 a+1,并把其赋值给a,否则a 还是a。
下面的代码更加直观一些:
> a <- 1
> f <- function(a) {
+ if(runif(1)>0.5) TRUE
+ else a
+ }
> f(a <- a+1);a
[1] TRUE
[1] 1
> f(a <- a+1);a
[1] TRUE
[1] 1
> f(a <- a+1);a
[1] TRUE
[1] 1
> f(a <- a+1);a
[1] 2
> f(a <- a+1);a
[1] TRUE
[1] 2
> f(a <- a+1);a
[1] 3
上述代码中,向函数 f() 传递传递参数 a <- a + 1 后,只有在随机数 runif(1) 小于0.5的时候,a 的值才会改变,即执行+1操作。否则传递TRUE值。因此,因为随机数 runif(1) 的随机性,每次调用函数 f()后 a 的值是不确定的。
ps:这样操作的代码可读性可见一斑,如果真的要赋值,为什么不在函数外部呢?如果要传递参数,用 = 再传递不就好了。函数参数弄那么复杂也是太无聊了了吧。
3. <<- 与 ->
刚刚学习R 的时候,我也曾经抱怨,为何不像py 或者其他语言一样,直接 = 大一统不就好了。
但其实,这个赋值号的意义本身是很清晰的。它是有方向的。
箭头的指向,比如 <-,也就是右边指向左边,表示的便是将右边的值赋值给左边,如果你喜欢,用 -> 甚至都是可以的。
> 5 -> s
> s
[1] 5
在 R 语言中,处在某一个环境层的代码都拥有读入上一环境层的变量的权限,但相反地,若只通过标准的赋值运算符 <- ,是无法向上一环境层写入变量的。若想在上一环境层进行赋值行为,即向上一层次写入变量,则需要用到 <<- (superassignment)运算符啦~
比如在闭包中使用超赋值:
f.gen <- function(){
runTimes <- 0
function(){
runTimes <<- runTimes + 1
print(runTimes)
}
}
f <- f.gen()
f()
此时每调用一次函数f,其内部的次数结果都会向上复制给外部的runTimes。
需要注意的是,一般说来, <<- 多用于在顶层环境中写入变量。然而需要注意的是,以 <<- 执行赋值时,会一直向上直至顶层进行变量查找。若在查找过程中寻找到该名称的变量,就会进行赋值操作。否则,将在顶层环境中创建变量并赋值。
(即如果想在多层函数的内部使用 <<- 改变全局环境中内容的话,需要注意中间函数是否存在相同名称的变量)
比如:
> glob <- function(){
+ d <- 5
+ nxt1 <- function(){d <<- e + 1}
+ e <- 2
+ nxt1()
+ d
+ }
> glob()
[1] 3
> d
Error: object 'd' not found
## 对比以下
> glob <- function(){
>
+ ##区别在这里,少了一行' d <- 5'
+
+ nxt1 <- function(){d <<- e + 1}
+ e <- 2
+ nxt1()
+ d
+ }
> glob()
[1] 3
> d
[1] 3
总结
- 赋值使用 <-
- 传参数 =
- 上一环境赋值 <<-