如何在data.table包中实现list构造函数的dot(。)别名?

时间:2017-07-22 11:36:37

标签: r data.table

我想知道.包中实现的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

1 个答案:

答案 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表达式的一部分,该表达式将点用于不同的目的。