我有一个函数f来计算调用它的环境的摘要.在这个简单的例子中,它只是总结了所有找到的对象.
f <- function(){
x <- ls(parent.frame())
sum(sapply(x, get, envir=parent.frame()))
}
g <- function(x = 7, y){
z <- 3
f()
}
Run Code Online (Sandbox Code Playgroud)
但是,如果从缺少参数的函数内调用它将引发错误.
R> g(y = 34)
[1] 44
R> g()
Error in FUN(c("x", "y", "z")[[2L]], ...) :
argument "y" is missing, with no default
Run Code Online (Sandbox Code Playgroud)
为了适当地处理它,我需要一种方法来从内部f判断y环境中g是否有其他任意对象是一个参数g,在这种情况下是否缺失.
尝试不同的解决方案
debug(f)
g()
Run Code Online (Sandbox Code Playgroud)
当然missing(y)不起作用,因为y不是一个论据f.更改missing评估的环境也不起作用,因为我们仍处于调用堆栈的同一级别:
Browse[2]> eval(missing(y), parent.frame())
Error in missing(y) : 'missing' can only be used for arguments
Browse[2]> identical(sys.frames(), eval(sys.frames(), parent.frame()))
[1] TRUE
Run Code Online (Sandbox Code Playgroud)
我能做的是确定是否y是g使用脏黑客的函数的参数
Browse[2]> eval(substitute(missing(a), list(a="x")), parent.frame())
[1] TRUE
Browse[2]> eval(substitute(missing(a), list(a="y")), parent.frame())
[1] TRUE
Browse[2]> eval(substitute(missing(a), list(a="z")), parent.frame())
[1] FALSE
Run Code Online (Sandbox Code Playgroud)
这会产生TRUE两个参数x,y但不会产生普通变量z.将它与tryCatch检查是否可以检索参数的组合将解决问题,但它非常脏:
is.argument <- eval(substitute(missing(a), list(a="y")), parent.frame())
if(is.argument){
tryCatch({
get("y", parent.frame())
FALSE
}, error = function(e) TRUE)
} else {
NA
}
Run Code Online (Sandbox Code Playgroud)
此外,我无法弄清楚如何定义is.argument任意参数,而不是"y"上面示例中明确说明的.
实际上,目的f是g在运行时调试.我可以打电话
R> debug(g)
R> g()
Run Code Online (Sandbox Code Playgroud)
单步执行并检查对象的状态f,或者我可能会设置options(error=recover)并发现自己调试g是否产生错误.在这两种情况下都应该有一个明确定义的调用堆栈,所以我想我的基本问题是它是否可以在不同的层次上查询,类似于帧堆栈(访问sys.frames()).我必须承认,这对我来说是深水.
想想f我自己的调整版本ls.str,可以像这样使用:
Browse[2]> ls.str() # Inside g()
x : num 7
y : <missing>
Run Code Online (Sandbox Code Playgroud)
一些挖后,ls.str和utils:::print.ls_str我发现,它实现了由同一个任务
for (nam in x) {
cat(nam, ": ")
o <- tryCatch(get(nam, envir = E, mode = M), error = function(e) e)
if (inherits(o, "error")) {
cat(if (length(grep("missing|not found", o$message)))
"<missing>"
else o$message, "\n", sep = "")
} else {
strO <- function(...) str(o, ...)
do.call(strO, strargs, quote = is.call(o) || is.symbol(o))
}
}
Run Code Online (Sandbox Code Playgroud)
除非有一个正确的方法来做到这一点,我只会做一个类似的黑客.
缺失参数的值在与环境关联的对列表中由称为“空符号”的奇数对象表示。事实证明,至少目前,“空符号”也是通过调用返回的quote(expr=)。(有关空符号的讨论请参见此处。)
该函数ls_safe()使用这两个事实来实现另一种缺失测试。它返回由其参数指定的环境中存在的非缺失变量的字符向量pos。
ls_safe <- function(pos=1) {
## Capture the parent environment's frame as a list
ll <- as.list(parent.frame(pos))
## Check for "missing" variables
ii <- sapply(ll, function(X) identical(X, quote(expr=)))
names(ll)[!ii]
}
## Then just use ls_safe() in place of ls()
f <- function(){
x <- ls_safe(pos=2)
sum(sapply(x, get, envir=parent.frame()))
}
g <- function(x = 7, y){
z <- 3
f()
}
g(99)
## [1] 102
g(99, 1000)
## [1] 1102
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5076 次 |
| 最近记录: |