16

我知道列表中的 NULL 值有时会让人绊倒。我很好奇为什么在特定情况下lapply似乎rapply会以NULL不同的方式对待价值观。

l <- list(a = 1, c = NULL, d = 3)

lapply(l,is.null)
$a
[1] FALSE

$c
[1] TRUE

$d
[1] FALSE

到现在为止还挺好。如果我们做同样的事情rapply呢?

rapply(l, is.null, how = "replace")
$a
[1] FALSE

$c
list()

$d
[1] FALSE

此示例非常简单且非递归,但您会在rapply嵌套列表中看到相同的行为。

我的问题是为什么?如果如 中所宣传的那样?rapply,它是“lapply 的递归版本”,为什么在这种情况下它们的行为如此不同?

4

1 回答 1

20

我想你回答了你自己的问题:因为它是递归的。

你不经常看到这个,但NULL实际上可以用来表示一个空序列,因为它是空的pairlist(类似于()Scheme 中如何终止一个列表。在内部,R 非常类似于 scheme)。

因此,rapply递归到空列表中,但完成后不费心将其转换回配对列表;你会得到一个常规的空列表。

实际上,rapply不要lapply真正以不同的方式对待 NULL:

> lapply(NULL, identity)
list()

您可以在 R 源代码 ( memory.c ) 中看到这正是配对列表的工作方式:

SEXP allocList(int n)
{
    int i;
    SEXP result;
    result = R_NilValue;
    for (i = 0; i < n; i++)
        result = CONS(R_NilValue, result);
    return result;
}
于 2011-08-24T04:31:24.243 回答