Skip to content

Commit eb997a0

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

File tree

8 files changed

+96
-16
lines changed

8 files changed

+96
-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

+30-10
Original file line numberDiff line numberDiff line change
@@ -358,9 +358,23 @@ 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+
{
365+
force(.f)
366+
},
367+
error = function(e) {
368+
cli_abort(
369+
c("Failed to convert {.code {f_arg}} to a slide computation.",
370+
"*" = "If you were trying to use the formula interface, maybe you forgot a tilde at the beginning.",
371+
"*" = "If you were trying to use the tidyeval interface, maybe you forgot to specify the name, e.g.: `my_output_col_name =`.",
372+
"*" = "If you were trying to use advanced features of the tidyeval interface such as `!! name_variable :=`, you might have forgotten the required leading comma."
373+
),
374+
parent = e
375+
)
376+
}
377+
)
364378

365379
if (rlang::is_quosures(.f)) {
366380
quosures <- rlang::quos_auto_name(.f) # resolves := among other things
@@ -463,10 +477,10 @@ as_slide_computation <- function(.f, ..., .ref_time_value_long_varnames, .ref_ti
463477
}
464478

465479
if (length(.f) > 2) {
466-
cli_abort("{.code {arg}} must be a one-sided formula",
480+
cli_abort("{.code {f_arg}} must be a one-sided formula",
467481
class = "epiprocess__as_slide_computation__formula_is_twosided",
468482
epiprocess__f = .f,
469-
call = call
483+
.call = .call
470484
)
471485
}
472486
if (rlang::dots_n(...) > 0L) {
@@ -486,7 +500,7 @@ as_slide_computation <- function(.f, ..., .ref_time_value_long_varnames, .ref_ti
486500
class = "epiprocess__as_slide_computation__formula_has_no_env",
487501
epiprocess__f = .f,
488502
epiprocess__f_env = env,
489-
arg = arg, call = call
503+
.f_arg = .f_arg, .call = .call
490504
)
491505
}
492506

@@ -513,26 +527,32 @@ as_slide_computation <- function(.f, ..., .ref_time_value_long_varnames, .ref_ti
513527
class = "epiprocess__as_slide_computation__cant_convert_catchall",
514528
epiprocess__f = .f,
515529
epiprocess__f_class = class(.f),
516-
arg = arg,
517-
call = call
530+
.f_arg = .f_arg,
531+
.call = .call
518532
)
519533
}
520534

521535
#' @rdname as_slide_computation
536+
#' @importFrom rlang caller_arg caller_env
522537
#' @keywords internal
523-
as_time_slide_computation <- function(.f, ...) {
538+
as_time_slide_computation <- function(.f, ..., .f_arg = caller_arg(.f), .call = caller_env()) {
524539
as_slide_computation(
525540
.f, ...,
541+
.f_arg = .f_arg,
542+
.call = .call,
526543
.ref_time_value_long_varnames = ".ref_time_value",
527544
.ref_time_value_label = "reference time value"
528545
)
529546
}
530547

531548
#' @rdname as_slide_computation
549+
#' @importFrom rlang caller_arg caller_env
532550
#' @keywords internal
533-
as_diagonal_slide_computation <- function(.f, ...) {
551+
as_diagonal_slide_computation <- function(.f, ..., .f_arg = caller_arg(.f), .call = caller_env()) {
534552
as_slide_computation(
535553
.f, ...,
554+
.f_arg = .f_arg,
555+
.call = .call,
536556
.ref_time_value_long_varnames = c(".version", ".ref_time_value"),
537557
.ref_time_value_label = "version"
538558
)

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

+15
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,21 @@ 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(
237+
error = TRUE,
238+
tibble(geo_value = 1, time_value = 1, value = 1) %>%
239+
as_epi_df(as_of = 1) %>%
240+
epi_slide(.window_size = 6, tibble(slide_value = mean(.x$value)))
241+
)
242+
expect_snapshot(
243+
error = TRUE,
244+
tibble(version = 1, geo_value = 1, time_value = 1, value = 1) %>%
245+
as_epi_archive() %>%
246+
epix_slide(tibble(slide_value = mean(.x$value)))
247+
)
233248
})
234249

235250
test_that("as_slide_computation works", {

0 commit comments

Comments
 (0)