-
Couldn't load subscription status.
- Fork 71
Description
@lionel- and I discussed the concept of a list-rcrd in more detail. Essentially this is a list that has some vectorized attributes that can get sliced alongside the list. We determined that one possible implementation of this idea is (in my own words):
-
The list itself is used as the core data structure.
-
The special vectorized attributes are stored as an attribute of the list. The easiest thing to do would be to store them as a named list in a single attribute called something like
vctrs:::vectorized. -
The list explicitly inherits from
"list", along with whatever extra class is used on top of that. Say itsvctrs_list_rcrd. -
The
vec_proxy.vctrs_list_rcrdmethod should return a data frame. The first column is a list-col containing the list. The remaining columns are the vectorized attributes.
This would currently work in vctrs, except for the fact that vec_is_list() has the following check: If x inherits explicitly from "list", then vec_proxy(x) must also be a list. This should currently fail here (although I think it doesn't because of a bug).
I don't remember exactly why we have that restriction, but it seems reasonable that we might try to remove it to allow these list-rcrds to work.
One possible implementation follows, but as @lionel- mentioned to me, the important part is that this doesn't require any vctrs specific helper, and can live completely outside vctrs.
library(vctrs)
new_list_rcrd <- function(x, vectorized, ..., class = character()) {
structure(
x,
`vctrs:::vectorized` = vectorized,
...,
class = c(class, "vctrs_list_rcrd", "list")
)
}
vec_proxy.vctrs_list_rcrd <- function(x, ...) {
vectorized <- attr(x, "vctrs:::vectorized")
x <- unclass(x)
cols <- list(`vctrs:::data` = x)
cols <- c(cols, vectorized)
new_data_frame(cols)
}
vec_restore.vctrs_list_rcrd <- function(x, to, ...) {
data <- x[["vctrs:::data"]]
x[["vctrs:::data"]] <- NULL
new_list_rcrd(data, x)
}
x <- new_list_rcrd(
x = list(a = 1:3, b = 2:5),
vectorized = list(
special1 = c(TRUE, FALSE),
special2 = c("x", "y")
)
)
x
#> $a
#> [1] 1 2 3
#>
#> $b
#> [1] 2 3 4 5
#>
#> attr(,"vctrs:::vectorized")
#> attr(,"vctrs:::vectorized")$special1
#> [1] TRUE FALSE
#>
#> attr(,"vctrs:::vectorized")$special2
#> [1] "x" "y"
#>
#> attr(,"class")
#> [1] "vctrs_list_rcrd" "list"
vec_slice(x, c(1, 1, 2))
#> $a
#> [1] 1 2 3
#>
#> $a
#> [1] 1 2 3
#>
#> $b
#> [1] 2 3 4 5
#>
#> attr(,"vctrs:::vectorized")
#> attr(,"vctrs:::vectorized")$special1
#> [1] TRUE TRUE FALSE
#>
#> attr(,"vctrs:::vectorized")$special2
#> [1] "x" "x" "y"
#>
#> attr(,"class")
#> [1] "vctrs_list_rcrd" "list"Created on 2020-08-05 by the reprex package (v0.3.0)