From e2291d0e4e8033b718731e132205b598774e63e8 Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Wed, 11 Oct 2023 09:53:47 -0400 Subject: [PATCH] Make vector recycling rules its own FAQ (#1885) * Make vector recycling rules its own FAQ * Add in extra new line * Use manual pkgdown redirects --- R/bind.R | 2 +- R/faq-developer.R | 11 +++ R/recycle.R | 74 +------------------ R/rep.R | 2 +- R/size.R | 2 +- R/slice-interleave.R | 2 +- R/type-data-frame.R | 2 +- _pkgdown.yml | 7 ++ man/data_frame.Rd | 2 +- man/df_list.Rd | 2 +- man/faq/developer/theory-recycling.Rmd | 59 +++++++++++++++ ...cling_rules.Rd => theory-faq-recycling.Rd} | 42 +++++------ man/vec-rep.Rd | 2 +- man/vec_bind.Rd | 2 +- man/vec_interleave.Rd | 2 +- man/vec_recycle.Rd | 2 +- man/vec_size.Rd | 2 +- 17 files changed, 109 insertions(+), 108 deletions(-) create mode 100644 man/faq/developer/theory-recycling.Rmd rename man/{vector_recycling_rules.Rd => theory-faq-recycling.Rd} (75%) diff --git a/R/bind.R b/R/bind.R index 45a1b295b..296a689e3 100644 --- a/R/bind.R +++ b/R/bind.R @@ -187,7 +187,7 @@ vec_rbind <- fn_inline_formals(vec_rbind, ".name_repair") #' @rdname vec_bind #' @param .size If, `NULL`, the default, will determine the number of rows in #' `vec_cbind()` output by using the tidyverse [recycling -#' rules][vector_recycling_rules]. +#' rules][theory-faq-recycling]. #' #' Alternatively, specify the desired number of rows, and any inputs of length #' 1 will be recycled appropriately. diff --git a/R/faq-developer.R b/R/faq-developer.R index b1fc0c98e..b9f2ec6b3 100644 --- a/R/faq-developer.R +++ b/R/faq-developer.R @@ -12,6 +12,17 @@ NULL #' @name theory-faq-coercion NULL +# Also see the `redirects:` section in `_pkgdown.yml` +# for `vector_recycling_rules.html` + +#' FAQ - How does recycling work in vctrs and the tidyverse? +#' +#' @includeRmd man/faq/developer/theory-recycling.Rmd description +#' +#' @name theory-faq-recycling +#' @aliases vector_recycling_rules +NULL + #' FAQ - How to implement ptype2 and cast methods? #' #' @includeRmd man/faq/developer/howto-coercion.Rmd description diff --git a/R/recycle.R b/R/recycle.R index d7e7bbf93..6c8a69fe7 100644 --- a/R/recycle.R +++ b/R/recycle.R @@ -1,80 +1,8 @@ -#' Recycling rules used by r-lib and the tidyverse -#' -#' @description -#' Recycling describes the concept of repeating elements of one vector to match -#' the size of another. There are two rules that underlie the "tidyverse" -#' recycling rules: -#' -#' - Vectors of size 1 will be recycled to the size of any other vector -#' -#' - Otherwise, all vectors must have the same size -#' -#' @section Examples: -#' -#' ```{r, warning = FALSE, message = FALSE, include = FALSE} -#' library(tibble) -#' ``` -#' -#' Vectors of size 1 are recycled to the size of any other vector: -#' -#' ```{r, comment = "#>"} -#' tibble(x = 1:3, y = 1L) -#' ``` -#' -#' This includes vectors of size 0: -#' -#' ```{r, comment = "#>"} -#' tibble(x = integer(), y = 1L) -#' ``` -#' -#' If vectors aren't size 1, they must all be the same size. Otherwise, an error -#' is thrown: -#' -#' ```{r, comment = "#>", error = TRUE} -#' tibble(x = 1:3, y = 4:7) -#' ``` -#' -#' @section vctrs backend: -#' -#' Packages in r-lib and the tidyverse generally use [vec_size_common()] and -#' [vec_recycle_common()] as the backends for handling recycling rules. -#' -#' - `vec_size_common()` returns the common size of multiple vectors, after -#' applying the recycling rules -#' -#' - `vec_recycle_common()` goes one step further, and actually recycles the -#' vectors to their common size -#' -#' ```{r, comment = "#>", error = TRUE} -#' vec_size_common(1:3, "x") -#' -#' vec_recycle_common(1:3, "x") -#' -#' vec_size_common(1:3, c("x", "y")) -#' ``` -#' -#' @section Base R recycling rules: -#' -#' The recycling rules described here are stricter than the ones generally used -#' by base R, which are: -#' -#' - If any vector is length 0, the output will be length 0 -#' -#' - Otherwise, the output will be length `max(length_x, length_y)`, and a -#' warning will be thrown if the length of the longer vector is not an integer -#' multiple of the length of the shorter vector. -#' -#' We explore the base R rules in detail in `vignette("type-size")`. -#' -#' @name vector_recycling_rules -#' @keywords internal -NULL - #' Vector recycling #' #' `vec_recycle(x, size)` recycles a single vector to a given size. #' `vec_recycle_common(...)` recycles multiple vectors to their common size. All -#' functions obey the [vctrs recycling rules][vector_recycling_rules], and will +#' functions obey the [vctrs recycling rules][theory-faq-recycling], and will #' throw an error if recycling is not possible. See [vec_size()] for the precise #' definition of size. #' diff --git a/R/rep.R b/R/rep.R index ac08a1719..7ff9b1003 100644 --- a/R/rep.R +++ b/R/rep.R @@ -36,7 +36,7 @@ #' the entire vector. #' #' For `vec_rep_each()`, an integer vector of the number of times to repeat -#' each element of `x`. `times` will be [recycled][vector_recycling_rules] to +#' each element of `x`. `times` will be [recycled][theory-faq-recycling] to #' the size of `x`. #' @param x_arg,times_arg Argument names for errors. #' diff --git a/R/size.R b/R/size.R index 1ee03f75e..46d287c5c 100644 --- a/R/size.R +++ b/R/size.R @@ -19,7 +19,7 @@ #' to `vec_size()` as [lengths()] is to [length()]. #' #' @seealso [vec_slice()] for a variation of `[` compatible with `vec_size()`, -#' and [vec_recycle()] to [recycle][vector_recycling_rules] vectors to common +#' and [vec_recycle()] to [recycle][theory-faq-recycling] vectors to common #' length. #' @section Invariants: #' * `vec_size(dataframe)` == `vec_size(dataframe[[i]])` diff --git a/R/slice-interleave.R b/R/slice-interleave.R index dd26557ac..0ebf91e95 100644 --- a/R/slice-interleave.R +++ b/R/slice-interleave.R @@ -20,7 +20,7 @@ #' @inheritParams vec_c #' #' @param ... Vectors to interleave. These will be -#' [recycled][vector_recycling_rules] to a common size. +#' [recycled][theory-faq-recycling] to a common size. #' #' @export #' @examples diff --git a/R/type-data-frame.R b/R/type-data-frame.R index 12d29cbbd..b06b3a371 100644 --- a/R/type-data-frame.R +++ b/R/type-data-frame.R @@ -39,7 +39,7 @@ new_data_frame <- fn_inline_formals(new_data_frame, "x") #' #' @section Properties: #' -#' - Inputs are [recycled][vector_recycling_rules] to a common size with +#' - Inputs are [recycled][theory-faq-recycling] to a common size with #' [vec_recycle_common()]. #' #' - With the exception of data frames, inputs are not modified in any way. diff --git a/_pkgdown.yml b/_pkgdown.yml index 812117b9f..6f4073c2a 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -131,3 +131,10 @@ reference: - vec_names - vec_as_location - vec_as_subscript + +# Needed to generate a `vector_recycling_rules` page, since it is an `@alias` +# but pkgdown doesn't currently generate pages for aliases. Other packages +# link to this old page name, so we don't want it to disappear. +# https://github.com/r-lib/pkgdown/issues/1876 +redirects: + - ["reference/vector_recycling_rules.html", "reference/theory-faq-recycling.html"] diff --git a/man/data_frame.Rd b/man/data_frame.Rd index 36fae58e7..334e30679 100644 --- a/man/data_frame.Rd +++ b/man/data_frame.Rd @@ -44,7 +44,7 @@ repair for convenience and performance. \section{Properties}{ \itemize{ -\item Inputs are \link[=vector_recycling_rules]{recycled} to a common size with +\item Inputs are \link[=theory-faq-recycling]{recycled} to a common size with \code{\link[=vec_recycle_common]{vec_recycle_common()}}. \item With the exception of data frames, inputs are not modified in any way. Character vectors are never converted to factors, and lists are stored diff --git a/man/df_list.Rd b/man/df_list.Rd index 91f6f2ae3..1ea4117f9 100644 --- a/man/df_list.Rd +++ b/man/df_list.Rd @@ -41,7 +41,7 @@ a helper function for data frame subclasses. \section{Properties}{ \itemize{ -\item Inputs are \link[=vector_recycling_rules]{recycled} to a common size with +\item Inputs are \link[=theory-faq-recycling]{recycled} to a common size with \code{\link[=vec_recycle_common]{vec_recycle_common()}}. \item With the exception of data frames, inputs are not modified in any way. Character vectors are never converted to factors, and lists are stored diff --git a/man/faq/developer/theory-recycling.Rmd b/man/faq/developer/theory-recycling.Rmd new file mode 100644 index 000000000..14046cf98 --- /dev/null +++ b/man/faq/developer/theory-recycling.Rmd @@ -0,0 +1,59 @@ + +```{r, child = "../setup.Rmd", include = FALSE} +``` + +Recycling describes the concept of repeating elements of one vector to match the size of another. There are two rules that underlie the "tidyverse" recycling rules: + +- Vectors of size 1 will be recycled to the size of any other vector + +- Otherwise, all vectors must have the same size + +# Examples + +```{r, warning = FALSE, message = FALSE, include = FALSE} +library(tibble) +``` + +Vectors of size 1 are recycled to the size of any other vector: + +```{r} +tibble(x = 1:3, y = 1L) +``` + +This includes vectors of size 0: + +```{r} +tibble(x = integer(), y = 1L) +``` + +If vectors aren't size 1, they must all be the same size. Otherwise, an error is thrown: + +```{r, error = TRUE} +tibble(x = 1:3, y = 4:7) +``` + +# vctrs backend + +Packages in r-lib and the tidyverse generally use [vec_size_common()] and [vec_recycle_common()] as the backends for handling recycling rules. + +- `vec_size_common()` returns the common size of multiple vectors, after applying the recycling rules + +- `vec_recycle_common()` goes one step further, and actually recycles the vectors to their common size + +```{r, error = TRUE} +vec_size_common(1:3, "x") + +vec_recycle_common(1:3, "x") + +vec_size_common(1:3, c("x", "y")) +``` + +# Base R recycling rules + +The recycling rules described here are stricter than the ones generally used by base R, which are: + +- If any vector is length 0, the output will be length 0 + +- Otherwise, the output will be length `max(length_x, length_y)`, and a warning will be thrown if the length of the longer vector is not an integer multiple of the length of the shorter vector. + +We explore the base R rules in detail in `vignette("type-size")`. diff --git a/man/vector_recycling_rules.Rd b/man/theory-faq-recycling.Rd similarity index 75% rename from man/vector_recycling_rules.Rd rename to man/theory-faq-recycling.Rd index b922747e9..a4f9f6961 100644 --- a/man/vector_recycling_rules.Rd +++ b/man/theory-faq-recycling.Rd @@ -1,20 +1,19 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/recycle.R -\name{vector_recycling_rules} +% Please edit documentation in R/faq-developer.R +\name{theory-faq-recycling} +\alias{theory-faq-recycling} \alias{vector_recycling_rules} -\title{Recycling rules used by r-lib and the tidyverse} +\title{FAQ - How does recycling work in vctrs and the tidyverse?} \description{ -Recycling describes the concept of repeating elements of one vector to match -the size of another. There are two rules that underlie the "tidyverse" -recycling rules: +Recycling describes the concept of repeating elements of one vector to +match the size of another. There are two rules that underlie the +“tidyverse” recycling rules: \itemize{ \item Vectors of size 1 will be recycled to the size of any other vector \item Otherwise, all vectors must have the same size } } \section{Examples}{ - - Vectors of size 1 are recycled to the size of any other vector: \if{html}{\out{
}}\preformatted{tibble(x = 1:3, y = 1L) @@ -33,8 +32,8 @@ This includes vectors of size 0: #> # i 2 variables: x , y }\if{html}{\out{
}} -If vectors aren't size 1, they must all be the same size. Otherwise, an error -is thrown: +If vectors aren’t size 1, they must all be the same size. Otherwise, an +error is thrown: \if{html}{\out{
}}\preformatted{tibble(x = 1:3, y = 4:7) #> Error in `tibble()`: @@ -46,15 +45,15 @@ is thrown: } \section{vctrs backend}{ - - -Packages in r-lib and the tidyverse generally use \code{\link[=vec_size_common]{vec_size_common()}} and -\code{\link[=vec_recycle_common]{vec_recycle_common()}} as the backends for handling recycling rules. +Packages in r-lib and the tidyverse generally use +\code{\link[=vec_size_common]{vec_size_common()}} and +\code{\link[=vec_recycle_common]{vec_recycle_common()}} as the backends for +handling recycling rules. \itemize{ \item \code{vec_size_common()} returns the common size of multiple vectors, after applying the recycling rules -\item \code{vec_recycle_common()} goes one step further, and actually recycles the -vectors to their common size +\item \code{vec_recycle_common()} goes one step further, and actually recycles +the vectors to their common size } \if{html}{\out{
}}\preformatted{vec_size_common(1:3, "x") @@ -74,18 +73,15 @@ vec_size_common(1:3, c("x", "y")) } \section{Base R recycling rules}{ - - -The recycling rules described here are stricter than the ones generally used -by base R, which are: +The recycling rules described here are stricter than the ones generally +used by base R, which are: \itemize{ \item If any vector is length 0, the output will be length 0 \item Otherwise, the output will be length \code{max(length_x, length_y)}, and a -warning will be thrown if the length of the longer vector is not an integer -multiple of the length of the shorter vector. +warning will be thrown if the length of the longer vector is not an +integer multiple of the length of the shorter vector. } We explore the base R rules in detail in \code{vignette("type-size")}. } -\keyword{internal} diff --git a/man/vec-rep.Rd b/man/vec-rep.Rd index 2f19c0507..f893ff78e 100644 --- a/man/vec-rep.Rd +++ b/man/vec-rep.Rd @@ -34,7 +34,7 @@ vec_unrep(x) the entire vector. For \code{vec_rep_each()}, an integer vector of the number of times to repeat -each element of \code{x}. \code{times} will be \link[=vector_recycling_rules]{recycled} to +each element of \code{x}. \code{times} will be \link[=theory-faq-recycling]{recycled} to the size of \code{x}.} \item{...}{These dots are for future extensions and must be empty.} diff --git a/man/vec_bind.Rd b/man/vec_bind.Rd index e20f6a628..fff4ae2d7 100644 --- a/man/vec_bind.Rd +++ b/man/vec_bind.Rd @@ -81,7 +81,7 @@ mentioned in error messages as the source of the error. See the \code{call} argument of \code{\link[rlang:abort]{abort()}} for more information.} \item{.size}{If, \code{NULL}, the default, will determine the number of rows in -\code{vec_cbind()} output by using the tidyverse \link[=vector_recycling_rules]{recycling rules}. +\code{vec_cbind()} output by using the tidyverse \link[=theory-faq-recycling]{recycling rules}. Alternatively, specify the desired number of rows, and any inputs of length 1 will be recycled appropriately.} diff --git a/man/vec_interleave.Rd b/man/vec_interleave.Rd index 5cc415027..bd4ce678f 100644 --- a/man/vec_interleave.Rd +++ b/man/vec_interleave.Rd @@ -14,7 +14,7 @@ vec_interleave( } \arguments{ \item{...}{Vectors to interleave. These will be -\link[=vector_recycling_rules]{recycled} to a common size.} +\link[=theory-faq-recycling]{recycled} to a common size.} \item{.ptype}{If \code{NULL}, the default, the output type is determined by computing the common type across all elements of \code{...}. diff --git a/man/vec_recycle.Rd b/man/vec_recycle.Rd index 71091fa7f..fcfe6111c 100644 --- a/man/vec_recycle.Rd +++ b/man/vec_recycle.Rd @@ -39,7 +39,7 @@ origin of a problem.} \description{ \code{vec_recycle(x, size)} recycles a single vector to a given size. \code{vec_recycle_common(...)} recycles multiple vectors to their common size. All -functions obey the \link[=vector_recycling_rules]{vctrs recycling rules}, and will +functions obey the \link[=theory-faq-recycling]{vctrs recycling rules}, and will throw an error if recycling is not possible. See \code{\link[=vec_size]{vec_size()}} for the precise definition of size. } diff --git a/man/vec_size.Rd b/man/vec_size.Rd index 6a257f4c1..472a3c1ba 100644 --- a/man/vec_size.Rd +++ b/man/vec_size.Rd @@ -119,6 +119,6 @@ list_sizes(list("a", 1:5, letters)) } \seealso{ \code{\link[=vec_slice]{vec_slice()}} for a variation of \code{[} compatible with \code{vec_size()}, -and \code{\link[=vec_recycle]{vec_recycle()}} to \link[=vector_recycling_rules]{recycle} vectors to common +and \code{\link[=vec_recycle]{vec_recycle()}} to \link[=theory-faq-recycling]{recycle} vectors to common length. }