我希望能够找到呼叫的…(点)参数所源自的环境.
脚本
例如,考虑一个函数
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(…)中的…所源自的环境:这是调用栏(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()实现效率不高.
>在rlang和/或基础R中实现env_dots()是否有更巧妙的方法?
>如何将match.call()调用移动到env_dots()中?
match.call(sys.function(-1),call = sys.call(-1),expand.dots = FALSE)确实有效.
备注 – 人们无法从rlang :: quos(…)推断出点的原始环境,因为有些quosures不会赋予调用环境(例如,当表达式是文字对象时).
最佳答案 我很遗憾找到一个旧问题,但我不确定所期望的行为是否明确. ……不是一个单一的表达;这是一个表达列表.在rlang quosures的情况下,每个表达式都有自己的环境.那么列表的环境应该是什么?
此外,可以修改…列表本身.考虑下面的例子,其中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()内部调用时应该返回什么?