Skip to content

Commit

Permalink
Make vector recycling rules its own FAQ (#1885)
Browse files Browse the repository at this point in the history
* Make vector recycling rules its own FAQ

* Add in extra new line

* Use manual pkgdown redirects
  • Loading branch information
DavisVaughan committed Oct 11, 2023
1 parent c5a8276 commit e2291d0
Show file tree
Hide file tree
Showing 17 changed files with 109 additions and 108 deletions.
2 changes: 1 addition & 1 deletion R/bind.R
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
11 changes: 11 additions & 0 deletions R/faq-developer.R
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
74 changes: 1 addition & 73 deletions R/recycle.R
Original file line number Diff line number Diff line change
@@ -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.
#'
Expand Down
2 changes: 1 addition & 1 deletion R/rep.R
Original file line number Diff line number Diff line change
Expand Up @@ -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.
#'
Expand Down
2 changes: 1 addition & 1 deletion R/size.R
Original file line number Diff line number Diff line change
Expand Up @@ -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]])`
Expand Down
2 changes: 1 addition & 1 deletion R/slice-interleave.R
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion R/type-data-frame.R
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
7 changes: 7 additions & 0 deletions _pkgdown.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
2 changes: 1 addition & 1 deletion man/data_frame.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/df_list.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

59 changes: 59 additions & 0 deletions man/faq/developer/theory-recycling.Rmd
Original file line number Diff line number Diff line change
@@ -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")`.
42 changes: 19 additions & 23 deletions man/vector_recycling_rules.Rd → man/theory-faq-recycling.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/vec-rep.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/vec_bind.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/vec_interleave.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/vec_recycle.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/vec_size.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit e2291d0

Please sign in to comment.