Skip to content

Commit

Permalink
Use vec_is_list() in map_depth()
Browse files Browse the repository at this point in the history
Fixes #920
  • Loading branch information
hadley committed Sep 9, 2022
1 parent 23c2b1b commit 40b59b2
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 21 deletions.
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@

## Features and fixes

* `map_depth()` now uses `vec_is_list()` to determine if there's more depth
to recurse into, as opposed to `!is_atomic(.x)` (#920).

* New `list_update()` which is similar to `list_modify()` but doesn't work
recursively (#822).

Expand Down
43 changes: 22 additions & 21 deletions R/map-if-at.R
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,15 @@ map_at <- function(.x, .at, .f, ...) {
#'
#' # Equivalent to:
#' map(x, map, paste, collapse = "/")
#'
#' # When ragged is TRUE, `.f()` will also be passed leaves at depth < `.depth`
#' x <- list(1, list(1, list(1, list(1, 1))))
#' str(x)
#' str(map_depth(x, 4, ~ length(unlist(.x)), .ragged = TRUE))
#' str(map_depth(x, 3, ~ length(unlist(.x)), .ragged = TRUE))
#' str(map_depth(x, 2, ~ length(unlist(.x)), .ragged = TRUE))
#' str(map_depth(x, 1, ~ length(unlist(.x)), .ragged = TRUE))
#' str(map_depth(x, 0, ~ length(unlist(.x)), .ragged = TRUE))
#' @export
map_depth <- function(.x, .depth, .f, ..., .ragged = FALSE) {
if (!is_integerish(.depth, n = 1, finite = TRUE)) {
Expand All @@ -116,28 +125,20 @@ map_depth_rec <- function(.x,
.atomic) {
if (.depth < 0) {
abort("Invalid depth")
}

if (.atomic) {
if (!.ragged) {
abort("List not deep enough")
} else if (.depth == 0) {
.f(.x, ...)
} else if (.depth == 1) {
map(.x, .f, ...)
} else {
if (vec_is_list(.x)) {
map(.x, map_depth_rec, .depth - 1, .f, ..., .ragged = .ragged)
} else {
if (.ragged) {
map(.x, .f, ...)
} else {
abort("List not deep enough")
}
}
return(map(.x, .f, ...))
}

if (.depth == 0) {
return(.f(.x, ...))
}

if (.depth == 1) {
return(map(.x, .f, ...))
}

# Should this be replaced with a generic way of figuring out atomic
# types?
.atomic <- is_atomic(.x)

map(.x, function(x) {
map_depth_rec(x, .depth - 1, .f, ..., .ragged = .ragged, .atomic = .atomic)
})
}
9 changes: 9 additions & 0 deletions man/map_if.Rd

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

0 comments on commit 40b59b2

Please sign in to comment.