本篇文章由 VeriMake 旧版论坛中备份出的原帖的 Markdown 源码生成
原帖标题为:关于命名空间 | R 函数的环境空间
原帖网址为:https://verimake.com/topics/248 (旧版论坛网址,已失效)
原帖作者为:dawdler(旧版论坛 id = 64,注册于 2020-08-17 14:01:22)
原帖由作者初次发表于 2021-07-29 03:42:03,最后编辑于 2021-07-29 03:42:03(编辑时间可能不准确)
截至 2021-12-18 14:27:30 备份数据库时,原帖已获得 270 次浏览、0 个点赞、0 条回复
R语言
解读R语言的环境空间
2. 函数的环境空间
2.1 环境空间的作用
在编写代码的过程中,我们需要引入环境空间的原因通常是为了防止名称冲突。一般来说,定义一个函数会自动建立一个环境空间,我们在某个语段调用一个函数,这个函数会有其在当下所存在的环境,同时,在运行这段代码时,函数运行也会自动生成一个环境,函数运行环境内部的对象是外部看不到的,内外也不会相互影响。
##function environment
add_func <- function(x,y) return(x + y)
print(add_func(1,1))
environment(add_func) <- emptyenv()
print(add_func(1,1))
以上代码的输出结果为:

可以看到,如果将函数的环境设置成空环境,则会显示找不到该函数。
2.2 给变量赋值
在学习R语言的过程中,我们对于使用<-
和=
等符号给变量赋值的操作应该已经很熟练了——在以往的经验中,每一次进行赋值的时候,程序都会在该语境中生成一个新的变量并赋给相应的值,在该语境内,如果已经有了同名的变量则用新的值替换掉旧的。
但是,结合环境空间的概念,函数运行的环境空间内的变量和上下文语境中的变量虽然是剥离开的,但理论上应该也存在可以改变函数外同名变量的函数或参数的。事实上,也确实存在——
##difference between <- and <<-
#using <-
x <- 0
add_func <- function() {x <- 1; x}
add_func()
print(x)
#using <<-
x <- 0
add_func <- function() {x <<- 1; x}
add_func()
print(x)
以上代码的输出结果为:

可以看到,在函数内使用<-
赋值不会改变定义在函数外的同名变量,这也是符合我们(新手)一贯认知的(函数参数命名与函数外的变量名不冲突),但是在函数体内使用<<-
或assign()
函数赋值时,程序不会直接在当前环境中创建一个新的变量,而是寻找父环境中是不是存在同名的变量,如果有,就对该变量进行赋值,如果没有,则继续向上搜索父环境,如果所有环境都没有找到,就在global环境中创建一个新的变量并赋值。
如果需要定义常量,可以使用lockbinding()
函数:
##constants
x = 1
lockBinding("x", env = .GlobalEnv)
x = 2
以上代码的输出结果为:

可以看到,虽然R本身没有给出常量的概念,但是通过lockbinding()
函数,可以锁定变量的值不可以被更改,也就相当于定义了一个常量啦!
Reference:
https://wolfsonliu.github.io/archive/2016/r-xue-xi-bi-ji-r-huan-jing-xiang-guan-de-cao-zuo.html