-
Notifications
You must be signed in to change notification settings - Fork 67
Peculiar interaction between sapply()
and a (named) vctr
#1416
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
Comments
Interestingly (to me, at least), library(vctrs)
x <- new_vctr(1:3, class = "foofy")
names(x) <- letters[1:3]
x
#> <foofy[3]>
#> a b c
#> 1 2 3
f <- function(x) "blah"
sapply(x, f)
#> [1] "blah" "blah" "blah"
purrr::map_chr(x, f)
#> a b c
#> "blah" "blah" "blah" Created on 2021-07-19 by the reprex package (v2.0.0.9000) |
The library(vctrs)
vctrs:::as.list.vctrs_vctr
#> function (x, ...)
#> {
#> out <- vec_chop(x)
#> if (vec_is_list(x)) {
#> out <- lapply(out, `[[`, 1)
#> }
#> out
#> }
#> <bytecode: 0x7f84270abe08>
#> <environment: namespace:vctrs>
x <- new_vctr(1:3, class = "foofy")
names(x) <- letters[1:3]
x
#> <foofy[3]>
#> a b c
#> 1 2 3
# This is what `as.list()` calls
vec_chop(x)
#> [[1]]
#> <foofy[1]>
#> a
#> 1
#>
#> [[2]]
#> <foofy[1]>
#> b
#> 2
#>
#> [[3]]
#> <foofy[1]>
#> c
#> 3
# But we could also specify indices, where it makes more sense to keep the
# inner names rather than "promote" them to outer names, which would not be defined
vec_chop(x, indices = list(1:2, 2:3, 3L))
#> [[1]]
#> <foofy[2]>
#> a b
#> 1 2
#>
#> [[2]]
#> <foofy[2]>
#> b c
#> 2 3
#>
#> [[3]]
#> <foofy[1]>
#> c
#> 3 But maybe we should consider special casing the as_list_vctrs_vctr <- function(x) {
names <- vec_names(x)
has_names <- !is.null(names)
if (has_names) {
x <- vec_set_names(x, NULL)
}
out <- vec_chop(x)
if (has_names) {
out <- vec_set_names(out, names)
}
if (vec_is_list(x)) {
out <- lapply(out, `[[`, 1)
}
out
}
as_list_vctrs_vctr(x)
#> $a
#> <foofy[1]>
#> [1] 1
#>
#> $b
#> <foofy[1]>
#> [1] 2
#>
#> $c
#> <foofy[1]>
#> [1] 3 |
This feels a bit morally similar to #1186 about Just based on what I see here, though, this seems like an easier call? It is surprising when |
We plan to use |
I recently re-implemented an existing S3 class using vctrs and have noticed that
sapply()
/lapply()
don't necessarily transfer the names of the input to the output. (I was not actually relying on this in any meaningful way, mind you, but I noticed that a piece of documentation started to render differently.)Why do the names of
x
not transfer, while those forz
do? What's weird is that it seems to vary by the function being applied. Here both have names. (Well, it's slightly less surprising now that I see the inner/outer name thing I show below.)Looking at the source of
sapply()
, these seem to be important differences. The vctrs-made vector returnsFALSE
foris.vector()
, which means it gets sent throughas.list()
andas.list()
also does something quite different forx
vs.z
, in terms of inner vs outer names.Created on 2021-07-19 by the reprex package (v2.0.0.9000)
The text was updated successfully, but these errors were encountered: