Почему rapply и lapply обрабатывают NULL по-разному? - PullRequest
16 голосов
/ 24 августа 2011

Мне известно, что значения 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», почему они ведут себя так по-разному в этом случае?

1 Ответ

20 голосов
/ 24 августа 2011

Я думаю, что вы ответили на свой вопрос: потому что он рекурсивный.

Вы не часто видите это, но на самом деле NULL может использоваться для обозначения пустой последовательности, потому что это пустая pairlist (аналогично тому, как () в Схеме завершает список. Внутренне R очень похож на схему).

Итак, rapply возвращается в пустой список, но не превращает его вpairlist, когда это сделано;вы получаете обычный пустой список.

На самом деле rapply и lapply на самом деле не трактуют NULL по-другому:

> lapply(NULL, identity)
list()

И вы можете увидеть в исходном коде R ( memory.c ) что именно так и должны работать pairlists:

SEXP allocList(int n)
{
    int i;
    SEXP result;
    result = R_NilValue;
    for (i = 0; i < n; i++)
        result = CONS(R_NilValue, result);
    return result;
}
...