【发布时间】:2015-01-07 15:27:36
【问题描述】:
问题
我有一个函数f,它计算调用它的环境的摘要。在这个简单的示例中,它只是对找到的所有对象求和。
f <- function(){
x <- ls(parent.frame())
sum(sapply(x, get, envir=parent.frame()))
}
g <- function(x = 7, y){
z <- 3
f()
}
但是,如果从缺少参数的函数中调用,则会引发错误。
R> g(y = 34)
[1] 44
R> g()
Error in FUN(c("x", "y", "z")[[2L]], ...) :
argument "y" is missing, with no default
为了适当地处理它,我需要一种方法来判断,从f 中,如果y 或g 环境中的其他任意对象是g 的参数,那么如果它不见了。
到目前为止我的尝试
我尝试不同的解决方案
debug(f)
g()
当然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
我能做的是确定 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
对于 x 和 y 两个参数产生 TRUE,但不是普通变量 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
}
此外,我不知道如何为任意参数定义is.argument,而不是上面示例中明确声明的"y"。
更新:目的
实际上,f 的目的是在运行时调试g。我可能会打电话
R> debug(g)
R> g()
通过它并使用f 检查对象的状态,或者我可以设置options(error=recover),然后发现自己正在调试g,如果它产生错误。在这两种情况下都应该有一个明确定义的调用堆栈,所以我想我的基本问题是它是否可以在不同的级别上进行查询,以类似于帧堆栈的方式(使用sys.frames() 访问)。我必须承认,这对我来说是深水。
将f 视为我自己的ls.str 的调整版本,可以这样使用:
Browse[2]> ls.str() # Inside g()
x : num 7
y : <missing>
在对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))
}
}
除非有适当的方法可以做到这一点,否则我只会做一个类似的 hack。
【问题讨论】:
-
这不是
g()和f()的问题吗?y是 到 前者的参数,如果参数丢失,g()应该在之前调用f()。 -
在大多数情况下我会同意,但我
f的目的是为了方便调试其他可能不是我自己编写的函数。 -
@Backlin 如果是这种情况,那么您将如何从这些函数中调用
f? -
请稍等,因为执行我要求的操作的根本原因显然不清楚,我将用更详细的解释更新问题。
-
缺失测试是否足够?如果
g()有一个名为y的正式名称,并且在其主体中分配给一个名为y的变量,你想发生什么?y是否应该通过f()中的 sapply 循环运行?
标签: r environment