Nested functions, sys.parent and environments in R

Here is a fancy recursive function that I wrote to help me understand the relationship between sys.parent () and the environment:

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 a 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! 

Much happens here, but I will try to ask a simple question: why does sys.parent () increase first by 1 (from 0 to 1), and then by 3 (i.e. 1, 4, 7, 10 ...)?

+8
r environment recursion
source share
2 answers

This is because you are calling dive through eval . The following is an example:

 > 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 a modified version that is incremented by one.

 > 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! 
+8
source share
 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! 
0
source share

All Articles