r - 如何在调用例程中获取调用函数的名称?

  显示原文与译文双语对照的内容
0 0

是否有" 非Internal " 方法获取调用方的名称,如函数 stop不明白?

我们的想法是,我有一个小函数,该函数检查输入和停止执行如果某些条件不满足 该函数由几个人,使用相同的验证的代码。 如果输入无效,则转储调用方的环境( 所以我看到参数传递至该函数) 和执行将终止。

简化的示例:

check <- function(x)
{
    if(x<0)
    {
        print(as.list(parent.frame()))
        evalq(stop("invalid input."), parent.frame())
    }
}
test <- function(x, y)
{
    check(x)
}

我以为计算表达式 quote(stop("blah"))在调用方的环境会使它显示调用方的名字。 但是,结果如下:

test(-1, 2)
# $x
# [1] -1
# 
# $y
# [1] 2
# 
# Error in eval(substitute(expr), envir, enclos) : invalid input.

这都不会改变我使用 parent.frame(n)n>1evalq.

所以这里有一个问题,两个问题: 1 。 是否有方法可以获取函数的名称创建一个环境( 假设它的创建方式不同)? 2 。 为什么上面的解决办法失败?

编辑: 我说上面的解决方法将失败,因为我想让错误信息显示为

Error in test(x, y) : invalid input.

好像 stop语句参与了其中一部分 test身体。 所以问题2 可以重申为: 2: 为什么不的计算 stop("invalid input.")捕获调用方的名称,以为是调用方的环境中计算?

时间:原作者:7个回答

0 0

请参见 ?match.call. 例如:

foo <- function() {
  match.call()[[1]]
}
foo()
as.character(foo())

这将产生

> foo()
foo
> 
> as.character(foo())
[1] "foo"

在代码的简化版本,

check <- function(x) {
  match.call()[[1]]
}
test <- function(y) {
  check(y)
}

> test(2)
check
> as.character(test(2))
[1] "check"

注意 match.call()可通过使用 sys.call()( 实际上,它调用 sys.call(sys.parent())) 上面做的调用时使用不带任何参数。 因此你可能需要参考 ?sys.call非常大的机遇。

原作者:
0 0

谢谢@GavinSimpson和@RicardoSporta,但我已经想清楚了 我将张贴答案以防有人:搜索与为此在SO 。

函数的名称生成当前调用中针对

deparse(sys.calls()[[sys.nframe()-1]])

这将返回一个字符串,该字符串contais不仅函数的名称,但整个调用对象。 名称就可以检索通过子集 sys.calls()[[sys.nframe()-1]]之前deparsing 。

我想是因为我写了一个函数,用来检查参数和中止程序执行在发生错误。 但是我想让这个函数( i ) 和( ii ) 显示转储环境的函数名称上一级在执行堆栈中。 ( i ) ( ii ) 中很容易,但我就深陷其中。

至于第二个问题在我的帖子,就会这样: 该表达式 stop("invalid input")计算的环境中 test函数,但这不是一回事参数作为表达式的一部分 test体内,因为执行堆栈 diferent此2 中方案。 在后一种情况中, stop仅有 test上面负责但首先,它有 eval, check然后 test向上。 返回的执行堆栈, sys.calls()不是是不是也要封闭环境。 这就是可能产生问题,而不会混淆。

原作者:
0 0

问题的应答#1是Gavin ( 使用 match.call) 。

但是,根据要描述,还应该看看 traceback(),可将其传递给其他函数的输出。


至于 Question #2

不是失败,而是完全按预期工作。 你现在看到的不是错误的错误在错误的真正意义上,而是从 stop(.)函数。

如果你看看 print(evalq)你们可以看到,该实例会接着调用 eval(substitute(expr), envir, enclos))其中 expr是你的 stop("invalid input.")

正确的解决方法是使用一个级别的quoting

  evalq(quote(stop("invalid input.")))
  # stop("invalid input.")
原作者:
0 0

说明一下,如Hadley已建议,可以使用 sys.call(). 例如:

funx = function(...) {
    callingFun = as.list(sys.call(-1))[[1]]
    calledFun = as.list(sys.call())[[1]]
    message(paste(callingFun, " is calling ", calledFun, sep=""))
}
funy = function(...) {funx(...)}
> funy(a = 1, b = 2)
funy is calling funx
原作者:
0 0

上面的函数来获取函数名,只需使用:

gsub(pattern="^([A-Za-z0-9]+)(({1})(.*)(){1})$",replacement="1",x=deparse(sys.call(-1)))
原作者:
...