deparse(substitute()) returns 通常是函数名,但在 for 循环内部调用时是函数代码
deparse(substitute()) returns function name normally, but function code when called inside for loop
我对 R 在一个非常具体的案例中的行为感到有点惊讶。假设我定义了一个函数 square
,它的参数的平方 returns,如下所示:
square <- function(x) { return(x^2) }
我想在另一个函数中调用这个函数,我也想在调用时显示它的名字。我可以使用 deparse(substitute())
来做到这一点。但是,请考虑以下示例:
ds1 <- function(x) {
print(deparse(substitute(x)))
}
ds1(square)
# [1] "square"
这是预期的输出,所以一切正常。但是,如果我传递包装在列表中的函数并使用 for 循环处理它,则会发生以下情况:
ds2 <- function(x) {
for (y in x) {
print(deparse(substitute(y)))
}
}
ds2(c(square))
# [1] "function (x) " "{" " return(x^2)" "}"
任何人都可以向我解释为什么会发生这种情况以及如何防止这种情况发生吗?
只要你在你的函数中使用 x
,它就会被计算,所以它是 "stops being an (unevaluated) expression" 和 "starts being its resulting values (evaluated expression)"。为防止这种情况,您必须在首次使用之前通过 substitute
捕获 x
。
substitute
的结果是一个对象,您可以像查询列表一样查询它。所以你可以使用
x <- substitute(x)
然后是x[[1]]
(函数名)和x[[2]]
以及后面的(函数的参数)
所以这有效:
ds2 <- function(x) {
x <- substitute(x)
# you can do `x[[1]]` but you can't use the expression object x in a
# for loop. So you have to turn it into a list first
for (y in as.list(x)[-1]) {
print(deparse(y))
}
}
ds2(c(square,sum))
## [1] "square"
## [1] "sum"
我对 R 在一个非常具体的案例中的行为感到有点惊讶。假设我定义了一个函数 square
,它的参数的平方 returns,如下所示:
square <- function(x) { return(x^2) }
我想在另一个函数中调用这个函数,我也想在调用时显示它的名字。我可以使用 deparse(substitute())
来做到这一点。但是,请考虑以下示例:
ds1 <- function(x) {
print(deparse(substitute(x)))
}
ds1(square)
# [1] "square"
这是预期的输出,所以一切正常。但是,如果我传递包装在列表中的函数并使用 for 循环处理它,则会发生以下情况:
ds2 <- function(x) {
for (y in x) {
print(deparse(substitute(y)))
}
}
ds2(c(square))
# [1] "function (x) " "{" " return(x^2)" "}"
任何人都可以向我解释为什么会发生这种情况以及如何防止这种情况发生吗?
只要你在你的函数中使用 x
,它就会被计算,所以它是 "stops being an (unevaluated) expression" 和 "starts being its resulting values (evaluated expression)"。为防止这种情况,您必须在首次使用之前通过 substitute
捕获 x
。
substitute
的结果是一个对象,您可以像查询列表一样查询它。所以你可以使用
x <- substitute(x)
然后是x[[1]]
(函数名)和x[[2]]
以及后面的(函数的参数)
所以这有效:
ds2 <- function(x) {
x <- substitute(x)
# you can do `x[[1]]` but you can't use the expression object x in a
# for loop. So you have to turn it into a list first
for (y in as.list(x)[-1]) {
print(deparse(y))
}
}
ds2(c(square,sum))
## [1] "square"
## [1] "sum"