Skip to content

Commit

Permalink
add passthrough for keep_units() when units are not provided (#394)
Browse files Browse the repository at this point in the history
* fixes #392

* test 2 currently fails; have to rethink

* undo reformatting

* possible fix?

* remove unneeded comment

* added to documentation and examples

* added more explanation of example
  • Loading branch information
d-morrison authored Feb 25, 2025
1 parent 892c6b9 commit 9e6502e
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 1 deletion.
27 changes: 26 additions & 1 deletion R/helpers.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
#' Provided for incompatible functions that do not preserve units. The user is
#' responsible for ensuring the correctness of the output.
#'
#' If \code{x} is not a \code{units} object
#' and \code{unit} is not provided by the user,
#' a warning is issued, and the output will also have no units
#' (see examples).
#'
#' @param FUN the function to be applied.
#' @param x first argument of \code{FUN}, of class \code{units}.
#' @param ... optional arguments to \code{FUN}.
Expand All @@ -17,9 +22,29 @@
#' x <- set_units(1:5, m)
#' keep_units(drop_units, x)
#'
#' # An example use case is with random number generating functions:
#' mu <- as_units(10, "years")
#' keep_units(rnorm, n = 1, x = mu)
#'
#' # units can be directly specified if needed; for example, with
#' # `rexp()`, the units of the rate parameter are the inverse of
#' # the units of the output:
#' rate <- as_units(3, "1/year")
#' keep_units(rexp, n = 1, x = rate, unit = units(1/rate))
#'
#' # if `x` does not actually have units, a warning is issued,
#' # and the output has no units:
#' rate2 <- 3
#' keep_units(rexp, n = 1, x = rate2)
#'
#' @export
keep_units <- function(FUN, x, ..., unit=units(x)) {
set_units(do.call(FUN, list(x, ...)), unit, mode="standard")
if (inherits(try(unit, silent = TRUE), "symbolic_units")) {
set_units(do.call(FUN, list(x, ...)), unit, mode = "standard")
} else {
warning("wrong `unit` specification.")
do.call(FUN, list(x, ...))
}
}

dfapply <- function(X, FUN, ...) {
Expand Down
20 changes: 20 additions & 0 deletions man/keep_units.Rd

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

15 changes: 15 additions & 0 deletions tests/testthat/test_helpers.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,18 @@ test_that("keep_units restores units", {

expect_identical(x, keep_units(drop_units, x))
})

test_that("keep_units warns when no units are provided", {
x <- 1:5

expect_warning(keep_units(sum, x))

expect_identical(suppressWarnings(keep_units(sum, x)), sum(x))
})

test_that("keep_units sets user-provided units", {
rate <- set_units(3, "1/min")
x <- keep_units(rexp, 3, rate, unit=units(1/rate))
expect_identical(units(x), units(1/rate))

})

0 comments on commit 9e6502e

Please sign in to comment.