egnha / valaddin

Functional input validation to make R functions more readable and robust
Other
33 stars 1 forks source link

Use dots_definitions() to capture checks #49

Closed egnha closed 7 years ago

egnha commented 7 years ago

The error message needs to capture its calling environment, because it may need to be interpolated by glue(). Therefore, we need to use dots_definitions(), rather than quos(), when capturing checks (in either firmly() or fasten()).

Corrected API should look like

backtick <- function(x) encodeString(x, quote = "`")
msg <- "{{backtick(.)}} is not positive"

f <- function(x, y) NULL

# Don't need to unquote `msg` because it will be tidily evaluated by the parser
firmly(f, is.numeric, msg := {isTRUE(. > 0} ~ quos(x, x - y))
egnha commented 7 years ago

Need to replace quos() with a analogue of dots_definitions() that supports splicing of definitions. (dots_definitions() only splices dots.)

egnha commented 7 years ago

Something like this will do the trick:

vld <- function(...) {
  dd <- rlang::dots_definitions(...)
  c(normalize_checks(dd$dots), label_checks(dd$defs))
}

label_checks <- function(defs)
  lapply(defs, `names<-`, c("msg", "chk"))

normalize_checks <- function(dots) {
  is_chk <- vapply(dots, is_check, logical(1))
  dots_splice <- lapply(dots[is_chk], rlang::eval_tidy)
  dots_checks <- lapply(dots[!is_chk], msg_empty)
  c(dots_checks, dots_splice)
}
is_check <- function(.)
  is.list(rlang::f_rhs(.))
msg_empty <- function(.)
  list(msg = rlang::quo(NULL), chk = .)

Then adapt the parser, accordingly.

egnha commented 7 years ago

Resolved on the quosures branch.