Skip to content

Commit

Permalink
Don't handle 0-length vectors like NULL
Browse files Browse the repository at this point in the history
Fixes #480
  • Loading branch information
hadley committed Aug 27, 2022
1 parent a5dddf1 commit 296bd59
Show file tree
Hide file tree
Showing 6 changed files with 21 additions and 14 deletions.
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@

## Features and fixes

* `pluck()` no longer replaces 0-length vectors with `default`; it now
only applies absent and `NULL` components.

* `map2()` and `pmap()` now recycle names of their first input if
needed (#783).

Expand Down
4 changes: 2 additions & 2 deletions R/pluck.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#' `pluck()` and `chuck()` implement a generalised form of `[[` that
#' allow you to index deeply and flexibly into data structures.
#' `pluck()` consistently returns `NULL` when an element does not
#' exist, `chuck()` always throws (or chucks) an error in that case.
#' exist while `chuck()` always throws (or chucks) an error.
#'
#' @param .x,x A vector or environment
#' @param ... A list of accessors for indexing into the object. Can be
Expand All @@ -15,7 +15,7 @@
#' [Dynamic dots][rlang::dyn-dots] are supported. In particular, if
#' your accessors are stored in a list, you can splice that in with
#' `!!!`.
#' @param .default Value to use if target is empty or absent.
#' @param .default Value to use if target is `NULL` or absent.
#'
#' @details
#' * You can pluck or chuck with standard accessors like integer
Expand Down
4 changes: 2 additions & 2 deletions man/pluck.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/pluck.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ SEXP pluck_impl(SEXP x, SEXP index, SEXP missing, SEXP strict_arg) {

end:
UNPROTECT(1);
return (Rf_length(x) == 0) ? missing : x;
return Rf_isNull(x) ? missing : x;
}


Expand Down
8 changes: 5 additions & 3 deletions tests/testthat/test-as-mapper.R
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,14 @@ test_that(".default replaces absent values", {
expect_equal(map_dbl(x, "b", .default = NA), c(2, NA, NA))
})

test_that(".default replaces elements with length 0", {
test_that(".default only replaces NULL elements", {
x <- list(
list(a = 1),
list(a = numeric()),
list(a = NULL),
list(a = numeric())
list()
)
expect_equal(map_dbl(x, "a", .default = NA), c(1, NA, NA))
expect_equal(map(x, "a", .default = NA), list(1, numeric(), NA, NA))
})

test_that("Additional arguments are ignored", {
Expand Down Expand Up @@ -75,3 +76,4 @@ test_that("complex types aren't supported for indexing", {
test_that("raw vectors are supported for indexing", {
expect_equal( as_mapper(1)(raw(2)), raw(1) )
})

14 changes: 8 additions & 6 deletions tests/testthat/test-pluck.R
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,17 @@ test_that("special indexes never match", {
})

test_that("special values return NULL", {
# unnamed input
# absent name
expect_null(pluck(list(1, 2), "a"))
expect_null(pluck(list(a = 1, b = 2), "c"))

# zero length input
expect_null(pluck(integer(), 1))

# past end
# outside of range
expect_null(pluck(1:4, 0))
expect_null(pluck(1:4, 10))
expect_null(pluck(1:4, 10L))
})

test_that("can pluck 0-lengths object", {
expect_equal(pluck(list(integer()), 1), integer())
})

test_that("handles weird names", {
Expand Down

0 comments on commit 296bd59

Please sign in to comment.