检查父函数中是否缺少参数

Bac*_*lin 6 environment r

我有一个函数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)

我能做的是确定是否yg使用脏黑客的函数的参数

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"上面示例中明确说明的.

更新:目的

实际上,目的fg在运行时调试.我可以打电话

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.strutils:::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)

除非有一个正确的方法来做到这一点,我只会做一个类似的黑客.

Jos*_*ien 3

缺失参数的值在与环境关联的对列表中由称为“空符号”的奇数对象表示。事实证明,至少目前,“空符号”也是通过调用返回的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)