在以下示例中,为什么f$i
和f$get_i()
会返回不同的结果?
factory <- function() {
my_list <- list()
my_list$i <- 1
my_list$increment <- function() {
my_list$i <<- my_list$i + 1
}
my_list$get_i <- function() {
my_list$i
}
my_list
}
f <- factory()
f$increment()
f$get_i() # returns 2
f$i # returns 1
答案 0 :(得分:6)
f <- factory()
使用my_list
创建my_list$i = 1
个对象,并将其分配给f
。现在f$i = 1
。
f$increment()
仅增加my_list$i
。它不会影响f
。
现在
f$get_i()
在
时返回(先前递增的)my_list$i
f$i
返回不受影响的f$i
它&#39;因为您使用了对全局对象进行操作的<<-
运算符。如果您将代码更改为
my_list$increment <- function(inverse) {
my_list$i <- my_list$i + 1
}
my_list
仅在increment
函数内增加。所以现在你得到了
> f$get_i()
[1] 1
> f$i
[1] 1
让我在您的代码中添加一行,以便我们看到increment
的肠子:
my_list$increment <- function(inverse) {
my_list$i <- my_list$i + 1
return(my_list$i)
}
现在,您可以看到<-
仅在increment
内部运作,<<-
在其外运行。
> f <- factory()
> f$increment()
[1] 2
> f$get_i()
[1] 1
> f$i
[1] 1
答案 1 :(得分:4)
根据@Cath关于“参考价值”的评论,我受到了启发,想出了这个。
library(data.table)
factory <- function() {
my_list <- list()
my_list$i <- data.table(1)
my_list$increment <- function(inverse) {
my_list$i[ j = V1:=V1+1]
}
my_list$get_i <- function() {
my_list$i
}
my_list
}
f <- factory()
f$increment()
f$get_i() # returns 2
V1
1: 2
f$i # returns 1
V1
1: 2
f$increment()
f$get_i() # returns 2
V1
1: 3
f$i # returns 1
V1
1: 3
答案 2 :(得分:4)
您编码的方式与功能范例非常相似。 R更常用作脚本语言。因此,除非您确切知道自己在做什么,否则使用&lt;&lt; - 或在函数中包含函数是不好的做法。
您可以在功能环境章节中找到解释here。
环境是执行代码的空间/框架。环境可以嵌套,就像函数一样。
创建功能时,您附加了一个可由environment
调用的机箱环境。这是封闭的环境。
该功能在另一个环境中执行,执行环境采用全新启动原则。执行环境是封闭环境的子环境。
例如,在我的笔记本电脑上:
> environment()
<environment: R_GlobalEnv>
> environment(f$increment)
<environment: 0x0000000022365d58>
> environment(f$get_i)
<environment: 0x0000000022365d58>
f是位于全球环境中的对象。
函数increment
附加了封闭环境0x0000000022365d58,函数factory
的执行环境。
我引用哈德利的话:
当你在另一个函数内创建一个函数时,封闭 子函数的环境是执行环境 父,并且执行环境不再是短暂的。
执行函数f时,将创建封闭环境,其中包含my_list
对象。
可以使用ls
命令评估:
> ls(envir = environment(f$increment))
[1] "my_list"
> ls(envir = environment(f$get_i))
[1] "my_list"
<<-
运算符正在父项环境中搜索所使用的变量。在这种情况下,找到的my_list
对象是直接上层环境中的对象,它是函数的封闭环境。
因此,当进行增量时,它仅在该环境中进行,而不是在全局中进行。
您可以通过替换increment
函数来看到它:
my_list$increment <- function() {
print("environment")
print(environment())
print("Parent environment")
print(parent.env(environment()))
my_list$i <<- my_list$i + 1
}
它给了我:
> f$increment()
[1] "environment"
<environment: 0x0000000013c18538>
[1] "Parent environment"
<environment: 0x0000000022365d58>
存储环境名称后,您可以使用get
来访问您的结果:
> my_main_env <- environment(f$increment)
> get("my_list", env = my_main_env)
$i
[1] 2
$increment
function ()
{
print("environment")
print(environment())
print("Parent environment")
print(parent.env(environment()))
my_list$i <<- my_list$i + 1
}
<environment: 0x0000000022365d58>
$get_i
function ()
{
print("environment")
print(environment())
print("Parent environment")
print(parent.env(environment()))
my_list$i
}
<environment: 0x0000000022365d58>