【发布时间】:2017-05-17 11:21:59
【问题描述】:
假设我有一个函数f,它接受一堆参数以及一个可选的额外参数。
f <- function(..., extra)
{
arglst <- lapply(quos(...), get_expr)
if(!missing(extra))
{
extra <- get_expr(enquo(extra))
arglst <- c(arglst, extra=extra)
}
arglst
## ... do something with argument list ... ##
}
f(a, extra=foo)
# [[1]]
# a
#
# $extra
# foo
请注意,我不想像这样评估参数,但我确实想获取传入的表达式,以便由其他代码进行评估。
新的rlang 包(它为dplyr 的下一个版本提供支持,即将在CRAN Real 上发布)为我在上面的f 中使用的惰性评估提供了广泛的设施。比如quos、get_expr和enquo都是rlang的函数。
在f 中,我处理extra 的部分实际上是样板代码:我想在其他函数中执行此操作,而不仅仅是在f 中。我不想每次都重写,所以我想我应该把它放到它自己的函数中:
doExtra <- function(arglst, extra)
{
if(!missing(extra))
{
extra <- get_expr(enquo(extra))
arglst <- c(arglst, extra=extra)
}
arglst
}
f2 <- function(..., extra)
{
arglst <- lapply(quos(...), get_expr)
arglst <- doExtra(arglst, extra)
arglst
}
问题是当我这样做时,doExtra 看到的extra 的值是从f2 传入的,而不是原来的:
f2(a, extra=foo)
# [[1]]
# a
#
# $extra
# extra
如何修改f 以隔离样板代码,而不会得到错误的结果?我可以直接操作doExtra的调用框架的环境,但这会非常难看。
【问题讨论】:
标签: r lazy-evaluation tidyverse