我希望能够找到 ...
所在的环境(点)调用的参数起源。
设想
例如,考虑一个函数
foo <- function(x, ...) {
# do something
}
我们想要一个函数
env_dots()
, 我们从 foo()
中调用,找到 ...
的原始环境调用foo()
, 即使调用 foo()
嵌套很深。也就是说,如果我们定义foo <- function(x, ...) {
# find the originating environment of '...'
env <- env_dots()
# do something
}
并嵌套调用
foo
,像这样,baz <- function(...) {
a <- "You found the dots"
bar(1, 2)
}
bar <- function(...)
foo(...)
然后调用
baz()
应该返回 ...
所在的环境在对 foo(...)
的(嵌套)调用中起源:这是调用 bar(1, 2)
的环境已制作,因为 2
(但不是 1
)被传递给 foo
的点.特别是,我们应该得到baz()$a
#> [1] "You found the dots"
env_dots()
的幼稚实现更新 —
env_dots()
,如此处所定义的,一般不会起作用,因为最终的 ...
可以由在调用堆栈的多个级别调用的参数填充。这是
env_dots()
的一种可能性:# mc: match.call() of function from which env_dots() is called
env_dots <- function(mc) {
# Return NULL if initial call invokes no dots
if (!rlang::has_name(mc, "...")) return(NULL)
# Otherwise, climb the call stack until the dots origin is found
stack <- rlang::call_stack()[-1]
l <- length(stack)
i <- 1
while (i <= l && has_dots(stack[[i]]$expr)) i <- i + 1
# return NULL if no dots invoked
if (i <= l) stack[[i + 1]]$env else NULL
}
# Does a call have dots?
has_dots <- function(x) {
if (is.null(x))
return(FALSE)
args <- rlang::lang_tail(x)
any(vapply(args, identical, logical(1), y = quote(...)))
}
这似乎有效:与
foo <- function(x, ...)
env_dots(match.call(expand.dots = FALSE))
我们得到
baz()$a
#> [1] "You found the dots"
bar(1, 2) # 2 gets passed down to the dots of foo()
#> <environment: R_GlobalEnv>
bar(1) # foo() captures no dots
#> NULL
问题
env_dots()
的上述实现效率不是很高。env_dots()
在 rlang 和/或 基础 R ? match.call()
在 env_dots()
内调用?match.call(sys.function(-1), call = sys.call(-1), expand.dots = FALSE)
确实会起作用。 备注 — 无法从
rlang::quos(...)
推断点的起源环境, 因为某些 quosures 不会被赋予调用环境(例如,当表达式是文字对象时)。
最佳答案
很抱歉提出一个老问题,但我不确定所需的行为是否明确。 ...
不是一个单一的表达式;这是一个表达式列表。如果是 rlang
quosures,每个表达式都有自己的环境。那么list的环境应该是怎样的呢?
此外,...
列表本身可以修改。考虑以下示例,其中 g
拿它的...
, 在它前面加上一个(未计算的)表达式 x+3
并将其传递给 f
.
f <- function(...) {rlang::enquos( ... )}
g <- function(...) {
a <- rlang::quo( x + 3 )
l <- rlang::list2( a, ... )
f(!!!l)
}
b <- rlang::quo( 5 * y )
g( b, 10 )
# [[1]]
# <quosure>
# expr: ^x + 3
# env: 0x7ffd1eca16f0
# [[2]]
# <quosure>
# expr: ^5 * y
# env: global
# [[3]]
# <quosure>
# expr: ^10
# env: empty
请注意,将其转换为
f
的三个 quosures 中的每一个有自己的环境。 (正如您在问题中指出的那样,10
之类的文字有一个空环境。这是因为值是相同的,与它在哪个环境中进行评估无关。)鉴于这种情况,假设的
env_dots()
应该是什么?在 f()
内部调用时返回?
关于r - 查找调用的 ...(点)参数的原始环境,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44773281/