Skip to content

Commit fc256bb

Browse files
committed
feat(epi[x]_slide): hint on forgotten syntax specifying comp
1 parent 44e7095 commit fc256bb

File tree

8 files changed

+86
-16
lines changed

8 files changed

+86
-16
lines changed

DESCRIPTION

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Type: Package
22
Package: epiprocess
33
Title: Tools for basic signal processing in epidemiology
4-
Version: 0.9.0
4+
Version: 0.10.1
55
Authors@R: c(
66
person("Jacob", "Bien", role = "ctb"),
77
person("Logan", "Brooks", , "[email protected]", role = c("aut", "cre")),

NEWS.md

+7
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
Pre-1.0.0 numbering scheme: 0.x will indicate releases, while 0.x.y will indicate PR's.
44

5+
# epiprocess 0.10
6+
7+
## Improvements
8+
- `epi_slide` and `epix_slide` now provide some hints if you forget a `~` when
9+
using a formula to specify the slide computation, and other bits of forgotten
10+
syntax.
11+
512
# epiprocess 0.9
613

714
## Breaking changes

R/grouped_epi_archive.R

+3-2
Original file line numberDiff line numberDiff line change
@@ -312,14 +312,15 @@ epix_slide.grouped_epi_archive <- function(
312312
cli_abort("If `f` is missing then a computation must be specified via `...`.")
313313
}
314314

315-
.slide_comp <- as_diagonal_slide_computation(quosures)
315+
.f_arg <- ".f" # dummy val, shouldn't be used since we're not using `.f`
316+
.slide_comp <- as_diagonal_slide_computation(quosures, .f_arg = .f_arg, .call = caller_env())
316317
# Magic value that passes zero args as dots in calls below. Equivalent to
317318
# `... <- missing_arg()`, but use `assign` to avoid warning about
318319
# improper use of dots.
319320
assign("...", missing_arg())
320321
} else {
321322
used_data_masking <- FALSE
322-
.slide_comp <- as_diagonal_slide_computation(.f, ...)
323+
.slide_comp <- as_diagonal_slide_computation(.f, ..., .f_arg = caller_arg(.f), .call = caller_env())
323324
}
324325

325326
# Computation for one group, one time value

R/slide.R

+3-1
Original file line numberDiff line numberDiff line change
@@ -147,14 +147,16 @@ epi_slide <- function(
147147
}
148148

149149
.f <- quosures
150+
.f_arg <- ".f" # dummy val, shouldn't be used since we're not using `.f`
150151
# Magic value that passes zero args as dots in calls below. Equivalent to
151152
# `... <- missing_arg()`, but `assign` avoids warning about improper use of
152153
# dots.
153154
assign("...", missing_arg())
154155
} else {
155156
used_data_masking <- FALSE
157+
.f_arg <- caller_arg(.f)
156158
}
157-
.slide_comp <- as_time_slide_computation(.f, ...)
159+
.slide_comp <- as_time_slide_computation(.f, ..., .f_arg = .f_arg, .call = caller_env())
158160

159161
.align <- rlang::arg_match(.align)
160162
time_type <- attr(.x, "metadata")$time_type

R/utils.R

+24-10
Original file line numberDiff line numberDiff line change
@@ -358,9 +358,17 @@ assert_sufficient_f_args <- function(.f, ..., .ref_time_value_label) {
358358
#' @importFrom rlang is_function new_function f_env is_environment missing_arg
359359
#' f_rhs is_formula caller_arg caller_env
360360
#' @keywords internal
361-
as_slide_computation <- function(.f, ..., .ref_time_value_long_varnames, .ref_time_value_label) {
362-
arg <- caller_arg(.f)
363-
call <- caller_env()
361+
as_slide_computation <- function(.f, ..., .f_arg = caller_arg(.f), .call = caller_env(), .ref_time_value_long_varnames, .ref_time_value_label) {
362+
f_arg <- .f_arg # for cli interpolation, avoid dot prefix
363+
withCallingHandlers({
364+
force(.f)
365+
}, error = function(e) {
366+
cli_abort(c("Failed to convert {.code {f_arg}} to a slide computation.",
367+
"*" = "If you were trying to use the formula interface, maybe you forgot a tilde at the beginning.",
368+
"*" = "If you were trying to use the tidyeval interface, maybe you forgot to specify the name, e.g.: `my_output_col_name =`.",
369+
"*" = "If you were trying to use advanced features of the tidyeval interface such as `!! name_variable :=`, you might have forgotten the required leading comma."),
370+
parent = e)
371+
})
364372

365373
if (rlang::is_quosures(.f)) {
366374
quosures <- rlang::quos_auto_name(.f) # resolves := among other things
@@ -463,10 +471,10 @@ as_slide_computation <- function(.f, ..., .ref_time_value_long_varnames, .ref_ti
463471
}
464472

465473
if (length(.f) > 2) {
466-
cli_abort("{.code {arg}} must be a one-sided formula",
474+
cli_abort("{.code {f_arg}} must be a one-sided formula",
467475
class = "epiprocess__as_slide_computation__formula_is_twosided",
468476
epiprocess__f = .f,
469-
call = call
477+
.call = .call
470478
)
471479
}
472480
if (rlang::dots_n(...) > 0L) {
@@ -486,7 +494,7 @@ as_slide_computation <- function(.f, ..., .ref_time_value_long_varnames, .ref_ti
486494
class = "epiprocess__as_slide_computation__formula_has_no_env",
487495
epiprocess__f = .f,
488496
epiprocess__f_env = env,
489-
arg = arg, call = call
497+
.f_arg = .f_arg, .call = .call
490498
)
491499
}
492500

@@ -513,26 +521,32 @@ as_slide_computation <- function(.f, ..., .ref_time_value_long_varnames, .ref_ti
513521
class = "epiprocess__as_slide_computation__cant_convert_catchall",
514522
epiprocess__f = .f,
515523
epiprocess__f_class = class(.f),
516-
arg = arg,
517-
call = call
524+
.f_arg = .f_arg,
525+
.call = .call
518526
)
519527
}
520528

521529
#' @rdname as_slide_computation
530+
#' @importFrom rlang caller_arg caller_env
522531
#' @keywords internal
523-
as_time_slide_computation <- function(.f, ...) {
532+
as_time_slide_computation <- function(.f, ..., .f_arg = caller_arg(.f), .call = caller_env()) {
524533
as_slide_computation(
525534
.f, ...,
535+
.f_arg = .f_arg,
536+
.call = .call,
526537
.ref_time_value_long_varnames = ".ref_time_value",
527538
.ref_time_value_label = "reference time value"
528539
)
529540
}
530541

531542
#' @rdname as_slide_computation
543+
#' @importFrom rlang caller_arg caller_env
532544
#' @keywords internal
533-
as_diagonal_slide_computation <- function(.f, ...) {
545+
as_diagonal_slide_computation <- function(.f, ..., .f_arg = caller_arg(.f), .call = caller_env()) {
534546
as_slide_computation(
535547
.f, ...,
548+
.f_arg = .f_arg,
549+
.call = .call,
536550
.ref_time_value_long_varnames = c(".version", ".ref_time_value"),
537551
.ref_time_value_label = "version"
538552
)

man/as_slide_computation.Rd

+14-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/_snaps/utils.md

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# as_slide_computation raises errors as expected
2+
3+
Code
4+
tibble(geo_value = 1, time_value = 1, value = 1) %>% as_epi_df(as_of = 1) %>%
5+
epi_slide(.window_size = 6, tibble(slide_value = mean(.x$value)))
6+
Condition
7+
Error in `as_slide_computation()`:
8+
! Failed to convert `tibble(slide_value = mean(.x$value))` to a slide computation.
9+
* If you were trying to use the formula interface, maybe you forgot a tilde at the beginning.
10+
* If you were trying to use the tidyeval interface, maybe you forgot to specify the name, e.g.: `my_output_col_name =`.
11+
* If you were trying to use advanced features of the tidyeval interface such as `!! name_variable :=`, you might have forgotten the required leading comma.
12+
Caused by error:
13+
! object '.x' not found
14+
15+
---
16+
17+
Code
18+
tibble(version = 1, geo_value = 1, time_value = 1, value = 1) %>%
19+
as_epi_archive() %>% epix_slide(tibble(slide_value = mean(.x$value)))
20+
Condition
21+
Error in `guess_period()`:
22+
! Not enough distinct values in `versions_with_updates` to guess the period.
23+

tests/testthat/test-utils.R

+11
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,17 @@ test_that("as_slide_computation raises errors as expected", {
230230
expect_error(as_time_slide_computation(5),
231231
class = "epiprocess__as_slide_computation__cant_convert_catchall"
232232
)
233+
234+
# If `.f` doesn't look like tidyeval and we fail to force it, then we hint to
235+
# the user some potential problems:
236+
expect_snapshot(error = TRUE,
237+
tibble(geo_value = 1, time_value = 1, value = 1) %>%
238+
as_epi_df(as_of = 1) %>%
239+
epi_slide(.window_size = 6, tibble(slide_value = mean(.x$value))))
240+
expect_snapshot(error = TRUE,
241+
tibble(version = 1, geo_value = 1, time_value = 1, value = 1) %>%
242+
as_epi_archive() %>%
243+
epix_slide(tibble(slide_value = mean(.x$value))))
233244
})
234245

235246
test_that("as_slide_computation works", {

0 commit comments

Comments
 (0)