Подтвердить что ты не робот

Как я могу ссылаться на локальную среду внутри функции, в 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(), и Томми дал хорошее объяснение, как использовать его и аналогичные функции в этом контексте.

4b9b3361

Ответ 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).