-1

在本书中,练习位于Environments本章第 10/23 页的第 1 节之后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

并获得一个包含基本环境和全局环境的列表。

我应该做些什么不同的事情以及如何做?

4

1 回答 1

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)
  }
}
于 2017-02-10T13:46:27.787 回答