`Advanced R` book: Найти все среды, содержащие привязку для`name`

В книге упражнение находится на странице 10/23 Environments глава, после раздела Iteration vs. Recursion, это

изменять where() найти все среды, содержащие привязку для name,

Вот, where() от pryr пакет. Прежде всего, чтобы быть уверенным, что я понимаю, что спрашивают: скажем, у меня есть имя mean, Это может относиться к:

> mean
function (x, ...) 
UseMethod("mean")
<bytecode: 0x2234b58>
<environment: namespace:base>

Но также, скажем, я присваиваю значение переменной с тем же именем:

> mean <- 3
> mean
[1] 3

Итак, сейчас (пожалуйста, поправьте меня, если я ошибаюсь), бывший mean связан baseenv() в то время как последний связан globalenv(), Правильный?

> ls(as.environment(globalenv()))
[1] "mean"
> which(ls(as.environment(baseenv()))=="mean")
[1] 671

Итак, я написал:

where2 <- function(k, name, env) {
  stopifnot(is.character(name), length(name) == 1)

  # Why does this only work when calling 'where' from
  # the 'pryr' package?
  # env <- to_env(env)

  # Hopefully the same as 'to_env'.
  # env <- as.environment(env)

  # Successful case.
  if(exists(name, env, inherits=FALSE)) {
    k <- list(k, env)
    where2(k, name, parent.env(env))
  } 

  # Base case or search one level up.
  if(identical(env, emptyenv())) {
    stop("Can't find ", name, call.=FALSE)
  } else {
    where2(k, name, parent.env(env))
  }
}

вдохновленный where функция от pryr пакет.

Я надеялся, что теперь смогу сделать (в приглашении R):

> source("./where2.r")
> mean <- 3
> k <- list()
> where2(k, "mean", parent.frame())
Error: Can't find mean

и получить список, содержащий в базовой и глобальной среде.

Что я должен делать по-другому и как?

1 ответ

Эта функция решает проблему:

    where_2 = function (name, env = parent.frame(), env_list = list()) 
{

  stopifnot(is.character(name), length(name) == 1)
  env <- as.environment(env)
  if (identical(env, emptyenv())) {
    if (length(env_list) == 0) {
      stop("Can't find ", name, call.=FALSE)
    } else {
      return(env_list)
    }
  } else if (exists(name, env, inherits = FALSE)) {
    env_list = append(env_list, env)
    where_2(name, parent.env(env), env_list = env_list)
  }
  else {
    where_2(name, parent.env(env), env_list = env_list)
  }
}
Другие вопросы по тегам