From fe832e480424f034d88777eced5e0cc8aa4d5d8a Mon Sep 17 00:00:00 2001 From: Lionel Henry Date: Wed, 5 Aug 2020 10:46:38 +0200 Subject: [PATCH 1/2] Recycle names in `map2()` Closes #779 --- src/map.c | 14 ++++++++++---- tests/testthat/test-map2.R | 7 +++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/map.c b/src/map.c index e14b2af0..f8bda74c 100644 --- a/src/map.c +++ b/src/map.c @@ -7,14 +7,20 @@ #include "utils.h" void copy_names(SEXP from, SEXP to) { - if (Rf_length(from) != Rf_length(to)) - return; - SEXP names = Rf_getAttrib(from, R_NamesSymbol); - if (Rf_isNull(names)) + if (names == R_NilValue) { return; + } + + R_len_t n = Rf_length(to); + + if (Rf_length(names) != n) { + names = short_vec_recycle(names, n); + } + PROTECT(names); Rf_setAttrib(to, R_NamesSymbol, names); + UNPROTECT(1); } void check_vector(SEXP x, const char *name) { diff --git a/tests/testthat/test-map2.R b/tests/testthat/test-map2.R index c307bd59..48a00bff 100644 --- a/tests/testthat/test-map2.R +++ b/tests/testthat/test-map2.R @@ -59,3 +59,10 @@ test_that("map2() with empty input copies names", { expect_identical(map2_chr(named_list, list(), identity), named(chr())) expect_identical(map2_raw(named_list, list(), identity), named(raw())) }) + +test_that("map2() recycle names (#779)", { + expect_identical( + map2(c(a = 1), 1:2, ~ .x), + list(a = 1, a = 1) + ) +}) From 332cc5d10df945335cc2a482564240c84a6e1b99 Mon Sep 17 00:00:00 2001 From: Lionel Henry Date: Wed, 5 Aug 2020 16:53:14 +0200 Subject: [PATCH 2/2] Add test for `pmap()` And NEWS bullet --- NEWS.md | 3 +++ tests/testthat/test-map2.R | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index ced4331b..2a5bfc79 100644 --- a/NEWS.md +++ b/NEWS.md @@ -11,6 +11,9 @@ ## Features and fixes +* `map2()` and `pmap()` now recycle names of their first input if + needed (#783). + * `every()` and `some()` now properly check the return value of their predicate function. It must now return a `TRUE`, `FALSE`, or `NA`. diff --git a/tests/testthat/test-map2.R b/tests/testthat/test-map2.R index 48a00bff..7941468a 100644 --- a/tests/testthat/test-map2.R +++ b/tests/testthat/test-map2.R @@ -60,9 +60,13 @@ test_that("map2() with empty input copies names", { expect_identical(map2_raw(named_list, list(), identity), named(raw())) }) -test_that("map2() recycle names (#779)", { +test_that("map2() and pmap() recycle names (#779)", { expect_identical( map2(c(a = 1), 1:2, ~ .x), list(a = 1, a = 1) ) + expect_identical( + pmap(list(c(a = 1), 1:2), ~ .x), + list(a = 1, a = 1) + ) })