Подтвердить что ты не робот

Почему ручка и лапша обрабатывают NULL по-другому?

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

4b9b3361

Ответ 1

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

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

Итак, 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;
}