Check if objects are of a specific size and recycle them if not
recycle_if_not.Rd
If any of the named expressions in ...
are not the specified size,
then the object attempts to be recycled to the size specified in the expression.
Expressions are evaluated and variables are assigned into the environment
specified by the .env
argument. The checking of size and the recycling
are from the vctrs package (using vctrs::vec_size
and vctrs::vec_recycle) and thus stick to the vctrs recycling rules.
Arguments
- ...
any number of named R expressions, in the form of:
name_of_obj_to_cast = size_to_cast_to
- .env
the environment to use for the evaluation of the recycling expressions & the assignment of the recycled variables. Cannot be the global environment.
- .class
class to assign to the error (passed to rlang::abort).
- .error_call
the call environment to use for the error (passed to rlang::abort).
Examples
# Will not alter the global environment so most examples here are wrapped with local().
x <- 1
recycle_if_not(x = 1) |> try()
# => Error: Argument `call` cannot be the global environment.
local({
x <- 1
recycle_if_not(x = 3)
x
})
#> [1] 1 1 1
local({
x <- rep(1, 4)
recycle_if_not(x = 1) |> try()
})
#> Error in eval(quote({ : Error in `recycle_if_not()`
#> ℹ Can't recycle `x` (size 4) to size 1.
# => Error : Can't recycle `x` (size 4) to size 1.
local({
x <- 1L
y <- 2.3
recycle_if_not(x = 3, y = 2)
cat(x, y, sep = ", ")
})
#> 1, 1, 1, 2.3, 2.3
# beware when using other objects as the size argument, e.g.:
local({
x <- 1L
y <- c(1, 1, 1)
recycle_if_not(x = y) |> try()
})
#> Error in eval(quote({ : Error in
#> ℹ Size argument for `x` is not a scalar integerish value: object length `3` of
#> class <numeric>.
# => Error : Size argument for `x` is not a scalar integerish value:
# object length `3` of class <numeric>.
# when using other objects, call vctrs::vec_size() on them first:
local({
x <- 1L
y <- c(1, 1, 1)
recycle_if_not(x = vctrs::vec_size(y))
x
})
#> [1] 1 1 1
# recycle_if_not works sequentially, so references to objects will
# be after they have been evaluated:
local({
x <- y <- 1
recycle_if_not(x = 3, y = vctrs::vec_size(x))
cat(length(x), length(y), sep = ", ")
})
#> 3, 3
myfunc <- \(x) {
recycle_if_not(x = 3)
x
}
x <- 1L
myfunc(x) # x is recycled to length 3 within the function
#> [1] 1 1 1
x # x is still scalar outside the function
#> [1] 1
local({
x <- 1
y <- 2
z <- 3
recycle_if_not(x = 2, y = 3, z = 4)
cat(x, y, z, sep = ", ")
})
#> 1, 1, 2, 2, 2, 3, 3, 3, 3
# the `.env` argument determines the expression and assignment environment:
local({
x <- 1
e <- new.env()
e$x <- 1
recycle_if_not(x = 3, .env = e)
cat(length(e$x), length(x), sep = ", ")
})
#> 3, 1
# names (lhs) are checked to be in the `.env` environment,
# throwing an error if not found:
local({
x <- 1
e <- new.env()
recycle_if_not(x = 3, .env = e) |> try()
})
#> Error in eval(quote({ : Error in `recycle_if_not()`
#> ℹ Objects `x` are not found in the `.env` environment specified.
# Error: Objects `x` are not found in the `.env` environment specified.
# for expressions (rhs), the `.env` argument is preferentially chosen,
# but if not found then the normal R scoping rules apply:
local({
x <- 3
e <- new.env()
e$z <- 1
recycle_if_not(z = x, .env = e)
cat(e$z)
})
#> 1 1 1