Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested functions, sys.parent, and environments in R

Here is a bizarre recursive function I've written to help me understand the relationships 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 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 ...)?

like image 694
zkurtz Avatar asked Jun 19 '13 02:06

zkurtz


People also ask

What is a parent environment in R?

The parent of the global environment is the last package that you loaded. The only environment that doesn't have a parent is the empty environment. The enclosing environment of a function is the environment where it was created. It determines where a function looks for variables.

Can you have nested functions in R?

There are two ways to create a nested function in the R programming language: Calling a function within another function we created. Writing a function within another function.

What is the environment function in R?

The environment is a virtual space that is triggered when an interpreter of a programming language is launched. Simply, the environment is a collection of all the objects, variables, and functions.

What is an example of a nested function?

For example, by nesting the AVERAGE and SUM function in the arguments of the IF function, the following formula sums a set of numbers (G2:G5) only if the average of another set of numbers (F2:F5) is greater than 50. Otherwise, it returns 0. The AVERAGE and SUM functions are nested within the IF function.


1 Answers

That's because you call dive via eval. The example below will make clear:

> 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.

> 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!
like image 156
kohske Avatar answered Oct 13 '22 01:10

kohske