我想知道.
包中实现的list
构造函数的点别名(data.table
)是怎样的。我要考虑的是这个功能:
library(data.table)
D = data.table(iris)
x1 = D[, .(Sepal.Length, Sepal.Width)] # dot alias
x2 = D[, list(Sepal.Length, Sepal.Width)] # standard name
identical(x1, x2) # TRUE
我试图在github上的源代码中找到它,但是它太密集了,我无法在任何合理的时间内理解它。
EDIT。
我知道这可以通过定义别名来轻松完成:. <- list
或. <- function(...) list(...)
。但是,这并不是我想要的。我想定义这样一个别名,所以它只能在给定的函数/方法的上下文中工作。
实施例
L <- .(1) # This throws error
L <- func(.(1)) # This works
实际上,我可以使用rlang
工具获得我想要的东西以进行整洁的评估。下面是一个简单的例子。
library(rlang)
func <- function(...) {
. <- list
eval_tidy(enexpr(x))
}
x1 <- func(.(1))
x2 <- list(1)
identical(x1, x2) # TRUE
所以我想知道这种功能是如何在data.table
专门实现的,因为它的开发时间早于rlang
?
答案 0 :(得分:2)
data.table在计算它们之前替换表达式中的点。它使用语言计算。
相关功能是replace_dot_alias
(请注意,重复使用此功能意味着您需要符合data.table的许可证):
replace_dot_alias <- function(e) {
# we don't just simply alias .=list because i) list is a primitive (faster to iterate) and ii) we test for use
# of "list" in several places so it saves having to remember to write "." || "list" in those places
if (is.call(e)) {
if (e[[1L]] == ".") e[[1L]] = quote(list)
for (i in seq_along(e)[-1]) if (!is.null(e[[i]])) e[[i]] = replace_dot_alias(e[[i]])
}
e
}
使用示例:
expr <- quote(.(a = b, c = .(sum(d))))
replace_dot_alias(expr)
#list(a = b, c = list(sum(d)))
然后执行修改后的表达式。该功能的一个缺点是它目前还没有分析点是否是bquote
表达式的一部分,该表达式将点用于不同的目的。