我有一个相当复杂的情况,我可能最终传递一个函数不存在的变量.我有一个很好的想法,当这种情况发生时,修复它将是困难的; 我很满意能够可靠地检测到条件并在这种情况下执行变通方法.我可以简单地使用
inherits(try(eval(possibly_missing_variable),silent=TRUE),"try-error")
Run Code Online (Sandbox Code Playgroud)
但如果可能的话,我想测试导致错误的具体情况object 'possibly_missing_variable' not found.(我可以尝试在错误消息中找到"未找到",但是我在过去的r-devel列表中已经被告诫,如果R以不同的语言运行,那么这将失败,以便翻译版本的出现错误消息.)
我尝试了各种组合deparse(substitute(...)),但它们似乎没有在调用堆栈上运行得足够多.这是我在一个可重复的例子中的最佳镜头:
f <- function(d) {
## test here
cat("'d' exists:",exists("d"),"\n") ## TRUE
cat("deparse(substitute(d)):",dd <- deparse(substitute(d)),"\n") ## OK
cat("exists('",dd,"'): ",exists(dd),"\n",sep="")
eval(d)
}
f2 <- function(ddd) {
f(ddd)
}
ddd <- 5
f2(junk)
Run Code Online (Sandbox Code Playgroud)
结果是:
'd' exists: TRUE
deparse(substitute(d)): ddd
exists('ddd'): TRUE
Error in eval(d) : object 'junk' not found
Run Code Online (Sandbox Code Playgroud)
我想要一个测试,它将正确地通知我(在遇到错误之前)评估将失败,因为在环境/封闭环境等堆栈中的任何地方都找不到相关对象.任何想法......?
更一般地说,有没有办法找出参数的最远上游名称("junk"在这种情况下)?如果我能做到,那就exists(farthest_upstream_name)解决了我的问题.
也许是这样的(从我对这个问题的第二个答案中偷来的)?
f <- function(d) {
## test here
ff <- sys.frames()
ex <- substitute(d)
ii <- rev(seq_along(ff))
for(i in ii) {
ex <- eval(substitute(substitute(x, env=sys.frames()[[n]]),
env = list(x = ex, n=i)))
}
if(!exists(deparse(ex))) stop("Substitute real error action here")
eval(d)
}
f2 <- function(ddd) {
f(ddd)
}
ddd <- 5
f2(junk)
## Error in f(ddd) (from #10) : Substitute real error action here
Run Code Online (Sandbox Code Playgroud)
我喜欢乔什·奥布莱恩的方法。但是,f按照此处的定义使用,即使传递的名称实际上具有活动绑定,如果它是在调用堆栈中的某个函数本地创建的(而不是在全局环境中),也可能会触发“不存在”错误条件)。此外,虽然可能与 Ben 的预期用法没有特别相关,但如果参数是表达式而不仅仅是名称,则会触发错误。
一个简单的修复方法是调整 Josh 的函数以包含is.symbol测试:
f <- function(d) {
## test here
ff <- sys.frames()
ex <- substitute(d)
ii <- rev(seq_along(ff))
for(i in ii) {
ex <- eval(substitute(substitute(x, env=sys.frames()[[n]]),
env = list(x = ex, n=i)))
}
if(is.symbol(ex) && !exists(deparse(ex))) {
stop("Substitute real error action here")
}
eval(d)
}
Run Code Online (Sandbox Code Playgroud)
所需的检查仍然有效:
f2 <- function(ddd) {
f(ddd)
}
f2(junk)
## Error in f(ddd) : Substitute real error action here
Run Code Online (Sandbox Code Playgroud)
但以下两种情况现在会通过而不是产生错误:
# case 1: argument to f is local to a calling function
f3 <- function() {
notjunk <- 999
f(notjunk)
}
f3()
## [1] 999
# case 2: argument to f is an expression
f2(5+5)
## [1] 10
Run Code Online (Sandbox Code Playgroud)
发生的情况f是,在重复应用 call-substitute-substitute 之后,ex在上面的情况 1 中设置为评估的参数本身,并在情况 2 中设置为通过的(尽管仍未评估)调用。在这两种情况下,exists单独的测试都会失败,因为ex它实际上不是一个名称(又名符号),但如果我们能够解决名称之外的问题,那么显然不存在就不是问题。