The title of the question pretty much says it: is there a way for an R function to find out if it is being called directly or from inside a for
or while
loop? sys.frame(0)
or parent.frame(1)
returns .GlobalEnv
whether the function was called directly or from inside one of those loops. So, is there some other way?
Thanks.
This is not a definitive answer, but I think your solution will be to look at the sys.status
, specifically the sys.parents
. The second example is for when the function is called within another function, and within a loop. Not sure how you differentiate this without knowing explicitly.
test <- function() sys.status()
for(i in 1:2){
print(test())
}
## $sys.calls
## $sys.calls[[1]]
## print(test())
##
## $sys.calls[[2]]
## test()
##
## $sys.calls[[3]]
## sys.status()
##
##
## $sys.parents
## [1] 0 0 2
##
## $sys.frames
## $sys.frames[[1]]
## <environment: 0x0479a1c8>
##
## $sys.frames[[2]]
## <environment: 0x0479a2fc>
##
## $sys.frames[[3]]
## <environment: 0x0479a334>
##
##
## $sys.calls
## $sys.calls[[1]]
## print(test())
##
## $sys.calls[[2]]
## test()
##
## $sys.calls[[3]]
## sys.status()
##
##
## $sys.parents
## [1] 0 0 2
##
## $sys.frames
## $sys.frames[[1]]
## <environment: 0x047993cc>
##
## $sys.frames[[2]]
## <environment: 0x04799570>
## $sys.frames[[3]]
## <environment: 0x047995a8>
and
test()
## $sys.calls
## $sys.calls[[1]]
## test()
##
## $sys.calls[[2]]
## sys.status()
##
##
## $sys.parents
## [1] 0 1
##
## $sys.frames
## $sys.frames[[1]]
## <environment: 0x04775500>
##
## $sys.frames[[2]]
## <environment: 0x04775538>
and
test_sq <- function() test()
for(i in 1:2){
print(test_sq())
}
## $sys.calls
## $sys.calls[[1]]
## print(test_sq())
##
## $sys.calls[[2]]
## test_sq()
##
## $sys.calls[[3]]
## test()
##
## $sys.calls[[4]]
## sys.status()
##
##
## $sys.parents
## [1] 0 0 2 3
##
## $sys.frames
## $sys.frames[[1]]
## <environment: 0x04766c60>
##
## $sys.frames[[2]]
## <environment: 0x04766dcc>
##
## $sys.frames[[3]]
## <environment: 0x04766e04>
##
## $sys.frames[[4]]
## <environment: 0x04766e3c>
##
##
## $sys.calls
## $sys.calls[[1]]
## print(test_sq())
##
## $sys.calls[[2]]
## test_sq()
##
## $sys.calls[[3]]
## test()
##
## $sys.calls[[4]]
## sys.status()
##
##
## $sys.parents
## [1] 0 0 2 3
##
## $sys.frames
## $sys.frames[[1]]
## <environment: 0x04765ac8>
##
## $sys.frames[[2]]
## <environment: 0x04765c34>
##
## $sys.frames[[3]]
## <environment: 0x04765c6c>
##
## $sys.frames[[4]]
## <environment: 0x04765d30>
and
test_sq()
## $sys.calls
## $sys.calls[[1]]
## test_sq()
##
## $sys.calls[[2]]
## test()
##
## $sys.calls[[3]]
## sys.status()
##
##
## $sys.parents
## [1] 0 1 2
##
## $sys.frames
## $sys.frames[[1]]
## <environment: 0x0475ce40>
##
## $sys.frames[[2]]
## <environment: 0x0475cee8>
##
## $sys.frames[[3]]
## <environment: 0x0475cf20>
Unfortunately for
doesn't appear in sys.calls
normally. While its a bit of a hack, you can actually override for
, causing it to be included:
`for` = function(iter, vec, expr) eval.parent(replace(sys.call(), 1, list(.Primitive('for'))))
in.for = function() '`for`' %in% lapply(sys.calls(), `[[`, 1)
my.fun = function() { print('before'); print(in.for()); print('after') }
my.fun()
# [1] "before"
# [1] FALSE
# [1] "after"
for (x in 1) my.fun()
# [1] "before"
# [1] TRUE
# [1] "after"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With