Skip to content

sys.function(0)

4 messages · Mick Jordan, Peter Dalgaard

#
As I understand 
https://stat.ethz.ch/R-manual/R-devel/library/base/html/sys.parent.html
sys.function(n) returns the function associated with stack frame n. 
Since frame 0 is defined as .GlobalEnv which is not associated with a 
function, I would expect this to always return NULL. However, it does not:

 > sys.function()
NULL
 > f <- function(x) sys.function(x)
 > f(0)
function(x) sys.function(x)
 > f(1)
function(x) sys.function(x)
 > f(2)
Error in sys.function(x) : not that many frames on the stack

Why the different behavior when sys.function(0) is called inside another 
function?

Mick Jordan
#
This is a documentation bug. The case "which = 0" differs between sys.frame() and sys.call()/sys.function(). For the latter, it means the current call/function, whereas sys.frame(0) is always the global envir. It is pretty clear from the underlying C code that the three functions treat their argument differently:

R_sysframe has

    if (n == 0)
        return(R_GlobalEnv);

    if (n > 0)
        n = framedepth(cptr) - n;
    else
        n = -n;

whereas the other two (R_syscall and R_sysfunction) omit the special treatment for n==0. Without this, n==0, comes out unchanged from the if-construct, indicating that one should go 0 frames up the stack (same as n==framedepth(cptr)).

Obviously, it won't work to document the "which" argument identically for all three functions...  

-pd

  
    
#
On 3/27/16 2:46 PM, peter dalgaard wrote:
Thanks. I didn't look at the C code this time trusting the documentation ;-)

A related question is why are sys.parent/parent.frame so permissive in 
their error checking? E.g:

 > sys.parent(-1)
[1] 0
 > sys.parent(-2)
[1] 0
 > sys.parent(1)
[1] 0
 > sys.parent(2)
[1] 0
 > parent.frame(4)
<environment: R_GlobalEnv>
 >
#
Dunno, really. Some strange things can happen with nonstandard evaluation, like having a function designed to evaluate something in the parent of its caller, but nonetheless sometimes being called from the command line. So things are sometimes defensively coded.

-pd