set.seed(2018) knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.path = "man/figures/README-", out.width = "100%" )
The goal of s3vec is to provide a wrapper around collections of s3 objects (of the same class) to make them behave like vectors of objects.
You can install s3vec from github with:
# install.packages("devtools") devtools::install_github("nbenn/s3vec")
Assume we have an s3 class point
, representing a point in 2 dimensions. Now we create 100 instances of point
and store them in the list points
.
point <- function(x, y) { stopifnot(is.numeric(x), is.numeric(y)) structure(list(x = x, y = y), class = "point") } points <- mapply(point, runif(100L), runif(100L), SIMPLIFY = FALSE)
We would like to implement a max
function that returns the point with the greatest distance from the origin. We cannot use s3 dispatch on point
, because our collection of points is a list. For a function like abs
, this is less of an issue, as it can be applied to individual objects by iterating through the list.
abs.point <- function(x) { sqrt(x$x ^ 2L + x$y ^ 2L) } abs(points[[1L]]) sapply(points[1:5], abs) max.point <- function(x, ...) { max(sapply(x, abs)) } max(points)
In order to get around this issue, s3vec
wraps an additional class (s3vec
) around such a list, holding several objects of the same type and bring this type to the surface of this wrapped object. Like this, s3 dispatch can be used for the point class.
library(s3vec) points <- as.s3vec(points) class(points) max(points)
Of course, in a simple scenario like this, one could argue that it makes more sense to use the point class as
points <- point(runif(5L), runif(5L)) max(points)
In which case, this enclosing class is not necessary. But a solution like this becomes more involved when for example there is structural variation among class instances (e.g. a mix of 2D and 3D points).
point <- function(coords) { stopifnot(is.numeric(coords)) structure(coords, class = "point") } points <- replicate(10L, point(runif(sample(2:3, 1L))), simplify = FALSE) sapply(points, length)
A completely vectorized approach as above is not as simple anymore and a list-based implementation might be better suited, in turn causing the problem described in the beginning.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.