Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inconsistent behaviour of map and pluck when indexing by name and location #1152

Closed
JBGruber opened this issue Oct 1, 2024 · 4 comments
Closed

Comments

@JBGruber
Copy link

JBGruber commented Oct 1, 2024

I was reading the pluck documentation when I stumbled on this interesting note in the examples:

# The map() functions use pluck() by default to retrieve multiple
# values from a list:

But when I wanted to try it, I got stuck. What my problem was is that mixing indexing by name and location does not work with map(), but I use it all the time with pluck. Here is an example where I would expect the outcome of both map calls to be the same:

obj1 <- list("a", list(1, elt = "foo"))
obj2 <- list("b", list(2, elt = "bar"))
x <- list(obj1, obj2)

purrr::map(x, c(2, "elt"))
#> [[1]]
#> NULL
#> 
#> [[2]]
#> NULL
purrr::map(x, \(i) purrr::pluck(i, 2, "elt"))
#> [[1]]
#> [1] "foo"
#> 
#> [[2]]
#> [1] "bar"

Created on 2024-10-01 with reprex v2.1.1

Session info
sessioninfo::session_info()
#> ─ Session info ───────────────────────────────────────────────────────────────
#>  setting  value
#>  version  R version 4.4.1 (2024-06-14)
#>  os       EndeavourOS
#>  system   x86_64, linux-gnu
#>  ui       X11
#>  language
#>  collate  en_GB.UTF-8
#>  ctype    en_GB.UTF-8
#>  tz       Europe/Amsterdam
#>  date     2024-10-01
#>  pandoc   3.1.11 @ /usr/lib/rstudio/resources/app/bin/quarto/bin/tools/x86_64/ (via rmarkdown)
#> 
#> ─ Packages ───────────────────────────────────────────────────────────────────
#>  package     * version date (UTC) lib source
#>  cli           3.6.3   2024-06-21 [1] CRAN (R 4.4.1)
#>  digest        0.6.37  2024-08-19 [1] CRAN (R 4.4.1)
#>  evaluate      0.24.0  2024-06-10 [1] CRAN (R 4.4.1)
#>  fastmap       1.2.0   2024-05-15 [1] CRAN (R 4.4.1)
#>  fs            1.6.4   2024-04-25 [1] CRAN (R 4.4.0)
#>  glue          1.7.0   2024-01-09 [1] CRAN (R 4.4.0)
#>  htmltools     0.5.8.1 2024-04-04 [1] CRAN (R 4.4.0)
#>  knitr         1.48    2024-07-07 [1] CRAN (R 4.4.1)
#>  lifecycle     1.0.4   2023-11-07 [1] CRAN (R 4.4.0)
#>  magrittr      2.0.3   2022-03-30 [1] CRAN (R 4.4.0)
#>  purrr         1.0.2   2023-08-10 [1] CRAN (R 4.4.0)
#>  reprex        2.1.1   2024-07-06 [1] CRAN (R 4.4.1)
#>  rlang         1.1.4   2024-06-04 [1] CRAN (R 4.4.1)
#>  rmarkdown     2.28    2024-08-17 [1] CRAN (R 4.4.1)
#>  rstudioapi    0.16.0  2024-03-24 [1] CRAN (R 4.4.0)
#>  sessioninfo   1.2.2   2021-12-06 [1] CRAN (R 4.4.0)
#>  vctrs         0.6.5   2023-12-01 [1] CRAN (R 4.4.0)
#>  withr         3.0.1   2024-07-31 [1] CRAN (R 4.4.1)
#>  xfun          0.47    2024-08-17 [1] CRAN (R 4.4.1)
#>  yaml          2.3.10  2024-07-26 [1] CRAN (R 4.4.1)
#> 
#>  [1] /home/johannes/R/x86_64-pc-linux-gnu-library/4.4
#>  [2] /usr/lib/R/library
#> 
#> ──────────────────────────────────────────────────────────────────────────────
@joakimlinde
Copy link

joakimlinde commented Oct 10, 2024

The c(2, "elt") argument looks odd to me. For vectors in R all elements have to be of the same type. R will coerce this into c("2", "elt"). Did you mean to say list(2, "elt") ?

purrr::map(x, list(2, "elt"))
#> [[1]]
#> [1] "foo"
#>
#> [[2]]
#> [1] "bar"

@JBGruber
Copy link
Author

It totally makes sense that list works and the approach with c does not! I didn't even consider that, thanks! But maybe it would make sense to add this as an example here:

#' map_int(x, c(2, 1))

If I make this mistake, others might as well? Maybe:

#' # if you want to mix location and name indexing, use list
#' purrr::map_chr(x, list(2, "elt"))

@joakimlinde
Copy link

There is already an example similar to this.

# Use a list to build an extractor that mixes numeric indices and names,
# and .default to provide a default value if the element does not exist
l2 |> map(list("num", 3))
#> [[1]]
#> [1] 3
#> 
#> [[2]]
#> [1] 103
#> 
#> [[3]]
#> NULL
#> 
l2 |> map_int(list("num", 3), .default = NA)
#> [1]   3 103  NA

@JBGruber
Copy link
Author

Great!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants