考虑这个函数a()
,它打印出传入的参数:
a <- function(x) {
message("The input is ", deparse(substitute(x)))
}
a("foo")
# The input is "foo"
tmplist <- list(x1 = 1, x2=2)
a(tmplist)
# The input is tmplist
有效。但是当从另一个函数调用a()
时,它不再打印出原始的参数名称:
b <- function(y) {
a(y)
}
b("foo")
# The input is y
b(tmplist)
# The input is y
似乎有效的一个解决方案是包含另一个substitute
和eval
:
a1 <- function(x) {
message("The input is ", deparse(eval(substitute(substitute(x)), parent.frame())))
}
a1("foo")
# The input is "foo"
tmplist <- list(x1 = 1, x2=2)
a1(tmplist)
# The input is tmplist
b1 <- function(y) {
a1(y)
}
b1("foo")
# The input is "foo"
b1(tmplist)
# The input is tmplist
但这似乎不够优雅。如果我添加另一层,它就会失败:
c1 <- function(z) {
b1(z)
}
c1("foo")
# The input is z
是否有一个很好的,一般的方法来获得原始论点?
答案 0 :(得分:3)
我不确定这会在所有情况下都能正常运行,但请尝试以下方法:
f0 <- function(x) {
nn <- substitute(x)
i <- 1
while(TRUE) {
on <- do.call("substitute", list(as.name(nn), parent.frame(i)))
if (on == nn) break;
nn <- on
i <- i + 1
}
message("The input is ", nn)
}
f1 <-function(.f1) f0(.f1)
f2 <- function(.f2) f1(.f2)
然后,
> f2(foo)
The input is foo
> f1(poo)
The input is poo
> f0(moo)
The input is moo
> f2(";(")
The input is ;(
> f1(":)")
The input is :)
> f0(":p")
The input is :p
答案 1 :(得分:2)
调整kohske的答案,这里有效,但如果变量在两个连续的帧中具有相同的名称,则不会过早地停止向上移动帧堆栈。我不知道它是否在所有情况下都能正常工作,但似乎可以满足我的需求。字符串与变量的引用与以前略有不同,但这对我的情况来说是可以的。
a <- function(x) {
newname <- substitute(x)
# Travel up the frame stack until we hit the top.
for(i in seq_len(sys.nframe())) {
oldname <- do.call("substitute", list(as.name(newname), parent.frame(i)))
newname <- oldname
}
message("The input is ", deparse(newname))
}
b <- function(y) a(y)
c <- function(z) b(z)
a("adsf")
# The input is adsf
a(foo)
# The input is foo
b("adsf")
# The input is adsf
b(foo)
# The input is foo
c("adsf")
# The input is adsf
c(foo)
# The input is foo
答案 2 :(得分:1)
虽然这本身就是一个有趣的问题,但我想知道最好的解决方案是将变量名称作为字符传递,即用引号括起来。那么这一切都不是必要的。如果需要与名称对应的对象,则可以使用get
或as.name
和do.call
获取该对象,具体取决于您在函数中使用它的方式。
> f0 <- function(x) {message("The input is ", x)}
> f1 <- function(.f1) f0(.f1)
> f2 <- function(.f2) f1(.f2)
> f2("aa")
The input is aa
> f1("bb")
The input is bb
> f0("cc")
The input is cc
答案 3 :(得分:0)
时递归调用函数怎么样?
deparse(substitute(x))!=deparse(eval(substitute(substitute(x)), parent.frame())