Here is a bizarre recursive function I've written to help me understand the relationships between sys.parent() and the environment:
这是一个奇怪的递归函数,我写的是为了帮助我理解sys.parent()和环境之间的关系:
dive = function(level = 1, max.depth = 5)
{
m = match.call()
print(paste("sys.frame() says", format(sys.frame())))
print(paste("sys.parent() says", sys.parent()))
print(paste("sys.frame(sys.parent()) says", format(sys.frame(sys.parent()))))
m[[2]] = m[[2]]+1
if(m[[2]] > max.depth)
stop("Not actually an error -- we're just tripping out!")
eval(m)
}
Running the function gives
运行该功能给出
dive(level = 1, max.depth = 5)
[1] "sys.frame() says <environment: R_GlobalEnv>"
[1] "sys.parent() says 0"
[1] "sys.frame(sys.parent()) says <environment: R_GlobalEnv>"
[1] "sys.frame() says <environment: R_GlobalEnv>"
[1] "sys.parent() says 1"
[1] "sys.frame(sys.parent()) says <environment: 0x2831dd0>"
[1] "sys.frame() says <environment: R_GlobalEnv>"
[1] "sys.parent() says 4"
[1] "sys.frame(sys.parent()) says <environment: 0x3b1dff8>"
[1] "sys.frame() says <environment: R_GlobalEnv>"
[1] "sys.parent() says 7"
[1] "sys.frame(sys.parent()) says <environment: 0x3b31c68>"
[1] "sys.frame() says <environment: R_GlobalEnv>"
[1] "sys.parent() says 10"
[1] "sys.frame(sys.parent()) says <environment: 0x3c238c0>"
Error in dive(level = 5, max.depth = 5) :
Not actually an error -- we're just tripping out!
There is a lot going on here, but I'll keep my question simple: Why does sys.parent() increment first by 1 (from 0 to 1) then subsequently by 3 (i.e., 1, 4, 7, 10 ...)?
这里有很多内容,但我会保持简单的问题:为什么sys.parent()首先增加1(从0增加到1)然后增加3(即1,4,7,10 .. 。)?
2 个解决方案
#1
8
That's because you call dive
via eval
. The example below will make clear:
那是因为你通过eval打电话。以下示例将明确:
> dive = function(level = 1, max.depth = 5)
+ {
+ m = match.call()
+ print(sys.calls())
+ cat("======================\n\n")
+ m[[2]] = m[[2]]+1
+ if(m[[2]] > max.depth)
+ stop("Not actually an error -- we're just tripping out!")
+ eval(m)
+ }
>
> dive(level = 1, max.depth = 3)
[[1]]
dive(level = 1, max.depth = 3)
======================
[[1]]
dive(level = 1, max.depth = 3)
[[2]]
eval(m)
[[3]]
eval(expr, envir, enclos)
[[4]]
dive(level = 2, max.depth = 3)
======================
[[1]]
dive(level = 1, max.depth = 3)
[[2]]
eval(m)
[[3]]
eval(expr, envir, enclos)
[[4]]
dive(level = 2, max.depth = 3)
[[5]]
eval(m)
[[6]]
eval(expr, envir, enclos)
[[7]]
dive(level = 3, max.depth = 3)
======================
Error in dive(level = 3, max.depth = 3) :
Not actually an error -- we're just tripping out!
Here is the modified version, which increments by one.
这是修改后的版本,增加1。
> dive = function(level = 1, max.depth = 5)
+ {
+ print(sys.calls())
+ cat("======================\n\n")
+ if(level+1 > max.depth)
+ stop("Not actually an error -- we're just tripping out!")
+ dive(level+1, max.depth)
+ }
>
> dive(level = 1, max.depth = 3)
[[1]]
dive(level = 1, max.depth = 3)
======================
[[1]]
dive(level = 1, max.depth = 3)
[[2]]
dive(level + 1, max.depth)
======================
[[1]]
dive(level = 1, max.depth = 3)
[[2]]
dive(level + 1, max.depth)
[[3]]
dive(level + 1, max.depth)
======================
Error in dive(level + 1, max.depth) :
Not actually an error -- we're just tripping out!
#2
0
1> dive = function(level = 1, max.depth = 5)
1+ {
1+ print(paste("sys.parent() says", sys.parent()))
1+ if(level+1 > max.depth)
1+ stop("Not actually an error -- we're just tripping out!")
1+ dive(level+1, 5)
1+ }
1> dive(level = 1, max.depth = 5)
[1] "sys.parent() says 0"
[1] "sys.parent() says 1"
[1] "sys.parent() says 2"
[1] "sys.parent() says 3"
[1] "sys.parent() says 4"
Error in dive(level + 1, 5) :
Not actually an error -- we're just tripping out!
#1
8
That's because you call dive
via eval
. The example below will make clear:
那是因为你通过eval打电话。以下示例将明确:
> dive = function(level = 1, max.depth = 5)
+ {
+ m = match.call()
+ print(sys.calls())
+ cat("======================\n\n")
+ m[[2]] = m[[2]]+1
+ if(m[[2]] > max.depth)
+ stop("Not actually an error -- we're just tripping out!")
+ eval(m)
+ }
>
> dive(level = 1, max.depth = 3)
[[1]]
dive(level = 1, max.depth = 3)
======================
[[1]]
dive(level = 1, max.depth = 3)
[[2]]
eval(m)
[[3]]
eval(expr, envir, enclos)
[[4]]
dive(level = 2, max.depth = 3)
======================
[[1]]
dive(level = 1, max.depth = 3)
[[2]]
eval(m)
[[3]]
eval(expr, envir, enclos)
[[4]]
dive(level = 2, max.depth = 3)
[[5]]
eval(m)
[[6]]
eval(expr, envir, enclos)
[[7]]
dive(level = 3, max.depth = 3)
======================
Error in dive(level = 3, max.depth = 3) :
Not actually an error -- we're just tripping out!
Here is the modified version, which increments by one.
这是修改后的版本,增加1。
> dive = function(level = 1, max.depth = 5)
+ {
+ print(sys.calls())
+ cat("======================\n\n")
+ if(level+1 > max.depth)
+ stop("Not actually an error -- we're just tripping out!")
+ dive(level+1, max.depth)
+ }
>
> dive(level = 1, max.depth = 3)
[[1]]
dive(level = 1, max.depth = 3)
======================
[[1]]
dive(level = 1, max.depth = 3)
[[2]]
dive(level + 1, max.depth)
======================
[[1]]
dive(level = 1, max.depth = 3)
[[2]]
dive(level + 1, max.depth)
[[3]]
dive(level + 1, max.depth)
======================
Error in dive(level + 1, max.depth) :
Not actually an error -- we're just tripping out!
#2
0
1> dive = function(level = 1, max.depth = 5)
1+ {
1+ print(paste("sys.parent() says", sys.parent()))
1+ if(level+1 > max.depth)
1+ stop("Not actually an error -- we're just tripping out!")
1+ dive(level+1, 5)
1+ }
1> dive(level = 1, max.depth = 5)
[1] "sys.parent() says 0"
[1] "sys.parent() says 1"
[1] "sys.parent() says 2"
[1] "sys.parent() says 3"
[1] "sys.parent() says 4"
Error in dive(level + 1, 5) :
Not actually an error -- we're just tripping out!