环境层次中某一层次的代码对它上级层次中所有变量至少有读的权限。但在另一方面,通过标准的<-运算符直接对上级层次变量进行写操作的不可行的。
如果希望对一个全局变量,或者更一般情况下,对当前层次的上级层次中任意变量进行写操作,你可以在当前层次使用超赋值运算符<<-,或者函数assign()。
►利用超赋值运算符对非局部变量进行写操作
> x <- 2
> u <- 6
> z <- 3
> two <- function( u ){
+ u <<- 2 * u
+ z <- 2 * u
+ }
> two( x )
> x
[1] 2
> u
[1] 4
> z
[1] 3
Ю x:尽管本例中x是函数two()的实际参数,调用后它的值仍为2。这是因为它的值2被复制到形式参数u,而参数u在此函数中被当作局部变量处理。于是,当u改变时,x的值并没有改变。
Ю z:两个z的值完全不相关,一个在顶层,另一个是two()的局部变量。对局部变量的改变不会影响全局变量。当然,两个变量使用同一个名字不是好的编程习惯。
Ю u:通过在two()中调用超赋值运算符,达到了改变上层次变量的目的。
<<-通常用于对顶层变量进行写操作,但严格而言,它的运作方式稍微有些不同。使用这个运算符对变量w进行写操作会导致对上级环境层次的查找,直到遇到含有该变量的第一个层次。如果没有找到,将会选取全局层次。
►用assign()函数对非局部变量进行写操作
也可以使用assign()函数对上层变量(upper-level variable)进行写操作。
> u <- 8
> two <- function( u ){
+ assign( "u", 2*u, pos=.GlobalEnv )
+ z <- 2 * z
+ }
> two( x )
> x
[1] 2
> u
[1] 4
这里,我们用函数assign()取代超赋值运算符。Assign()让R把2*u(此处u是局部变量)的值向上赋值给调用栈中的变量u,具体而言是顶层环境下的u。在本例中,比局部变量所在层级更高的环境只有顶层环境,但是如果我们有个函数调用链,超赋值也是可以达到更高层级的环境。
在assign()中使用字符串来引用变量的做法非常方便。