Как я могу ссылаться на локальную среду внутри функции, в R?
[Этот вопрос был разрешен в чате Spacedman, но я отправляю его для других в будущем.]
У меня есть функция myFunc
, которая создает внутри нее localFunc
. (NB: это не в пакете, а в глобальной среде.) Я хотел бы знать, где localFunc
существует в пути поиска, так как я бы хотел проанализировать его с помощью mvbutils::foodweb
.
Вот пример:
myFunc <- function(){
require(data.table)
require(mvbutils)
localFunc <- function(x){
return(as.data.table(x))
}
vecPrune <- c("localFunc",ls("package:data.table"))
ix <- match("data.table",search())
tmpWeb <- foodweb(where = c(1,ix), prune = vecPrune, plotting = FALSE)
return(tmpWeb)
}
Однако вызов myFunc()
не указывает, что localFunc
вызывает data.table()
. Это неверно - что дает?
(NB: аргумент where
указывает путь поиска.)
Обновление 1: Как указывает Томми и Spacedman, трюк заключается в том, чтобы указать environment()
. Вызов foodweb()
относится к where = c(1, ix)
. Индекс 1
является ошибкой. Это возникло из-за того, что .GlobalEnv
, который часто (всегда?) Является первым элементом в векторе search()
, является правильным местом для поиска. Это ошибочно. Вместо этого следует обратиться к environment()
, и правильный вызов ниже. (NB: ix
указывает расположение data.table()
на выходе search()
.)
tmpWeb <- foodweb(where = c(environment(),ix), prune = vecPrune, plotting = FALSE)
Это появляется в ответе этого вопроса в функции с именем checkScriptDependencies
, которая переносит код из файла R script в локальную функцию, который затем анализируется на foodweb
. Это ограниченный пример использования environment()
, и Томми дал хорошее объяснение, как использовать его и аналогичные функции в этом контексте.
Ответы
Ответ 1
Чтобы получить текущую среду, просто вызовите environment()
.
В общем случае sys.frame
возвращает любую среду, находящуюся в стеке вызовов, и sys.nframe
возвращает текущую глубину стека вызовов. sys.frames
возвращает список всех сред в стеке вызовов.
environment(f)
возвращает среду закрытия для функции f
(где она будет искать функции и глобальные переменные).
parent.env(e)
возвращает родительскую среду, в которой он будет выглядеть, если символ не найден в e
.
f <- function() {
function() list(curEnv=environment(), parent=parent.env(environment()),
grandParent=parent.env(parent.env(environment())), callStack=sys.frames(),
callStackDepth=sys.nframe())
}
g <- function(f, n=2) if (n>2) g(f, n-1) else f()
floc <- f() # generate a local function
g(floc, 3) # call it
Это вызовет локальную функцию floc
с глубиной стека 3. Она возвращает список с текущей средой, родительский (локальная среда в f
), и это великий родитель (где f
был, поэтому globalenv
). Он также возвращает список фреймов стека (среды). Это среда для рекурсивных вызовов в g
(кроме последней, которая является текущей средой floc
).