Как отметил @ eipi10 в комментариях, некоторые служебные вызовы функций становятся менее важными, когда используются большие объемы данных:
list1 <- as.list(rep(1, 50000))
list2 <- as.list(rep(1, 50000))
microbenchmark(map2(list1, list2, sum), mapply(sum, X=list1, Y=list2, SIMPLIFY = FALSE))
Unit: milliseconds
expr min lq mean median uq max neval cld
map2(list1, list2, sum) 73.84420 78.21917 82.53853 79.48526 81.28048 218.9266 100 b
mapply(sum, X = list1, Y = list2, SIMPLIFY = FALSE) 51.92849 54.66514 61.34755 56.99206 58.67459 204.2119 100 a
mapply
использует .Internal
, а purr::map2
использует.Call
для доступа к базовым функциям C, которые выполняют обработку.Существуют некоторые различия в том, как они работают, особенно в отношении оценки аргументов и в том, как R ищет основной код.
Справка R по .Internal
дает загадочное сообщение:
.Internal выполняет вызов внутреннего кода, встроенного в интерпретатор R.
Только истинным мастерам R следует рассмотреть возможность использования этой функции, и только разработчики R могут добавлять в список внутренних функций.
Однако в руководстве по внутренним ресурсам R объясняется, что:
Код C, скомпилированный в R во время сборки, может вызываться непосредственно в так называемых примитивах или через интерфейс .Internal, который очень похож на интерфейс .External, за исключением синтаксиса.Точнее, R поддерживает таблицу имен функций R и соответствующих функций C для вызова, которые по соглашению все начинаются с 'do_' и возвращают SEXP.Эта таблица (R_FunTab в файле src / main / names.c) также указывает, сколько аргументов функции требуется или разрешено, должны ли аргументы оцениваться перед вызовом, и является ли функция «внутренней» в смыслечто он должен быть доступен через интерфейс .Internal или напрямую доступен; в этом случае он печатается в R как .Primitive.
и
Небольшое количество примитивовявляются специальными, а не встроенными, то есть они вводятся с неоцененными аргументами.Это явно необходимо для языковых конструкций и операторов присваивания, а также для && и ||которые условно оценивают свой второй аргумент, и ~, .Internal, call, expression, missing, on.exit, quote и replace, которые не оценивают некоторые из своих аргументов.
Файл справки для .Call
notes:
Если одна из этих функций будет использоваться часто, укажите PACKAGE (чтобы ограничить поиск одной DLL) или передайте .NAME в качестве одного из собственных объектов символа.Поиск символов может занять много времени, особенно когда загружено много пространств имен.
Это означает, что при использовании .Call
уходит некоторое время на поиск DLL-библиотек для функций.Стоит отметить, что purr::map2
не указывает имя пакета при использовании .Call
, и это может уменьшить необходимые служебные данные.