如何在调用函数时为用户提供统一和简单语法时,如何混合函数参数的标准和惰性评估?
我是dplyr
的忠实粉丝,但我不太喜欢它,它会让你使用区分函数名称(例如select
与{{1当你想把你的论点表达为"混合包时,你会想到如何写函数调用太多了:有些表达为字符串,对于其他你想要懒惰评价的人,对于其他人,您需要标准评估。另请参阅John Mount的blog post on wrapr,了解另一个例子,即由于标准与惰性评估而导致做一件简单事情变得过于复杂。
这是编写我所知道的select_
表达式的最简单方法
dyplyr::select
在玩完之后,这是我之后解决方案的草稿:
x <- "disp"
select_(mtcars, "mpg", ~cyl, x)
它有效,但当然在效率方面执行得很差; - )
为了更好地理解R中的评估,特别是我想知道如何摆脱select2 <- function(dat, ...) {
args <- substitute(list(...))
## Express names as character //
idx <- which(sapply(args, class) == "name")[-1]
## We don't care about the first one as it's going to be
## substituted anyway
if (length(idx)) {
for (ii in idx) args[[ii]] <- as.character(args[[ii]])
}
## Ensure `c()` //
args[[1]] <- quote(c)
## Standard eval for variables containing actual column name //
idx <- which(!eval(args) %in% names(dat)) + 1
if (length(idx)) {
for (ii in idx) args[[ii]] <- eval(as.name(args[[ii]]))
}
## Indexing expression //
exprsn <- substitute(dat[, J], list(J = eval(args)))
eval(exprsn)
}
x <- "disp"
(select2(mtcars, "mpg", cyl, x))
循环,以及如何最好地利用现有的功能for
和dplyr
个软件包以及lazyeval
,do.call("[.data.frame", ...)
等基础R功能。特别是索引和分配方法(with()
和"[.*"
)以及如何直接调用它们对我来说仍然是一个谜。