r-lib / vctrs

Generic programming with typed R vectors
https://vctrs.r-lib.org
Other
287 stars 66 forks source link

Wrapper types #1080

Open lionel- opened 4 years ago

lionel- commented 4 years ago
lionel- commented 4 years ago

Can wrapper types be wrapped? If yes, we'll have symmetry problems on permutation of inputs. Or maybe they have to implement their own double dispatch methods.

lionel- commented 4 years ago

errors are also higher order types.

lionel- commented 4 years ago

Related discussion in #340

lionel- commented 4 years ago

Maybe we just need to support default methods? There will be a symmetry issue if both higher order types implement a default method, and maybe in that case we could require both types to agree on a common method.

vec_ptype2.omit.default <- function(x, y, ...) {
  new_omit(vec_ptype2(zap_omit(x), y, ...))
}
vec_ptype2.AsIs.default <- function(x, y, ...) {
  new_as_is(vec_ptype2(zap_as_is(x), y, ...))
}

vec_ptype2.omit.AsIs <- function(x, y, ...) {
  # somehow combine omit and AsIs
}
vec_ptype2.AsIs.omit <- function(x, y, ...) {
  # somehow combine omit and AsIs
}
hadley commented 4 years ago

We could also have some standard way to declare that two higher order types are orthogonal, so that there's some way to declare a composable vec_ptype/vec_cast.

thebioengineer commented 4 years ago

Would it be possible to have a vec_ptype2.default.AsIs()/vec_cast.default.AsIs() as well?

From what I understand is we need to define how in either direction we convert the vctr we create should go when casting and converting. My use case (from #1162), it would be nice to simply define how both vec_cast and vec_ptype2 should behave in a generic sense when interacting with my vctr class and deferring when there is then a more clearly defined cast/ptype2 mechanism.

ie. for {colortable} I would love to be able to:

vec_ptype2.color_vctr.color_vctr <- function(x, y, ...){
  data_type <- get_ptype2(x, y, ...)
  new_color_vctr(data_type)
}
vec_ptype2.default.color_vctr <- vec_ptype2.color_vctr.color_vctr
vec_ptype2.color_vctr.default <- vec_ptype2.color_vctr.color_vctr

vec_cast.color_vctr.default <- function(x, to, ...) coerce_to_color_vctr(x, to)
vec_cast.default.color_vctr <- function(x, to, ...) coerce_color_vctr(x, to)

## helper functions
coerce_color_vctr <- function(x, to){
  text_color <- field(x, ".text_color")
  background <- field(x, ".background")
  style <- field(x, ".style")
  x <- field(x, "vctr")

  x <- vec_c(x, get_ptype2(x, to))
  color_vctr(x, text_color = text_color, background = background, style = style)
}

coerce_to_color_vctr <- function(x, to){
  x <- vec_cast(x, get_ptype2(x, to))
  color_vctr(x)
}
lionel- commented 4 years ago

I think this is the same as what is described in https://github.com/r-lib/vctrs/issues/1080#issuecomment-656111560?

thebioengineer commented 4 years ago

Oh, so vec_ptype2.color_vctr.default() would work in "both directions"?

I was thinking we would need the likes of vec_ptype2.default.omit() because based on my understanding with the current format of vec_ptype2 it seems like we need to define both "directions" of ptype. ie. vec_ptype2.character.numeric() might be different than vec_ptype.numeric.character(). Would this line also extend to casting?

lionel- commented 4 years ago

Yes it would work in both directions for all classes, as long as the other class doesn't have a default method as well. In that case, a specific method would be needed.

lionel- commented 4 years ago

We could also have some standard way to declare that two higher order types are orthogonal, so that there's some way to declare a composable vec_ptype/vec_cast.

It seems the orthogonality means the types are mixins? In that case we probably need to think about this in conjunction with restore methods appropriate for mixins.