pryr包where函数调用to_env未找到却能运行的原因探究
关于pryr包where函数中to_env的疑问解答
核心原因是to_env是pryr包的内部非导出函数:
- 这类函数仅对包内部的代码可见,不会对外暴露——你通过
library(pryr)加载包后,在全局环境里直接调用to_env是找不到它的。 - 原生的
pryr::where()运行在pryr包的专属环境中,这个环境能直接访问包内所有内部函数,所以to_env可以正常调用。
当你把where函数的代码复制到全局环境并重命名后,新函数的执行环境变成了全局环境,而全局环境中不存在to_env,因此会触发"找不到函数"的错误。
让复制后的函数正常运行的两种方法
直接调用pryr内部的to_env
修改代码中的to_env为pryr:::to_env(三个冒号用于访问包的非导出函数),修改后的函数如下:my_where <- function (name, env = parent.frame()) { stopifnot(is.character(name), length(name) == 1) env <- pryr:::to_env(env) if (identical(env, emptyenv())) { stop("Can't find ", name, call. = FALSE) } if (exists(name, env, inherits = FALSE)) { env } else { my_where(name, parent.env(env)) } }自行实现to_env的功能
to_env的核心作用是将不同类型的输入(环境对象、字符串、数字)转换为对应的环境对象,你可以把它的逻辑内嵌到函数里,或者单独实现:# 先实现to_env的简化版本 to_env <- function(x) { if (is.environment(x)) return(x) if (is.character(x)) return(as.environment(x)) if (is.numeric(x)) return(sys.frame(x)) stop("Invalid environment specification", call. = FALSE) } # 再定义你的where函数 my_where <- function (name, env = parent.frame()) { stopifnot(is.character(name), length(name) == 1) env <- to_env(env) if (identical(env, emptyenv())) { stop("Can't find ", name, call. = FALSE) } if (exists(name, env, inherits = FALSE)) { env } else { my_where(name, parent.env(env)) } }
内容的提问来源于stack exchange,提问作者Allrounder
相关产品推荐
相关产品推荐

