Open moodymudskipper opened 5 years ago
Have also trying()
, which has the same interface as suppressing_warnings()
These should be about right, maybe error messages could be better handled but good enough.
Just add small feature : suppressing_warnings
and trying
should support a vector of .regex
, either try them in turn or just collapse the regex "(...)|(...)
.
trying <- tag::tag(
args = alist(.regex="*", .silent = FALSE,
.outFile = getOption("try.outFile", default = stderr())),
pattern = {
# try call in parent env, keep "visible" info
res <- try(
withVisible(eval.parent(CALL(eval = FALSE))),
silent = TRUE, .outFile)
# if error, see if it satisfies condition
if(inherits(res, "try-error")) {
cond <- if (is.character(.regex))
grepl(.regex, res) else
rlang::as_function(.regex)(res)
if(cond) message(res) else
stop(res, call. = FALSE)
invisible(res)
} else {
# if no error, return result with relevant visibility
if(res$visible) res$value else invisible(res$value)
}
})
x1 <- trying("xx")$stop("hello")
#> Error: Error in eval(expr, p) : hello
x1
#> Error in eval(expr, envir, enclos): object 'x1' not found
x2 <- trying("ll")$stop("hello")
#> Error in eval(expr, p) : hello
x2
#> [1] "Error in eval(expr, p) : hello\n"
#> attr(,"class")
#> [1] "try-error"
#> attr(,"condition")
#> <simpleError in eval(expr, p): hello>
trying_and_catching <- tag::tag(
args = alist(.regex=, finally=),
pattern = {
# wrap .regex in list if it was given unwrapped
if (inherits(.regex, "formula")) .regex <- list(.regex)
on.exit(if(!missing(finally)) eval.parent(substitute(finally)))
tryCatch(
eval.parent(CALL(eval = FALSE)),
error = function(e){
# test all elements
for (regex in .regex) {
# it must be a two sided formula
if(!rlang::is_formula(regex, lhs=TRUE))
stop(".regex should be a 2 sided formula or a list of such elements")
# regex[[2]] is lhs as call, regex[-3] is lhs as formula
detected <-
if(is.character(regex[[2]])) {
grepl(regex[[2]], e$message)
} else {
detect_fun <- rlang::as_function(regex[-3])
detect_fun(e$message)
}
if(detected) {
# regex[-2] is rhs as formula
f <- rlang::as_function(regex[-2])
return(f(e$message))
}
}
stop(e)
}
)
})
# using regex
trying_and_catching("xx" ~ warning("foo",call. = F))$stop("hello")
#> Error in eval(expr, p): hello
trying_and_catching("ll" ~ warning("foo",call. = F))$stop("hello")
#> Warning: foo
trying_and_catching("ll" ~ warning("foo",call. = F), finally = print("baz"))$stop("hello")
#> [1] "baz"
#> Warning: foo
# using function
trying_and_catching(startsWith(.,"hell") ~ warning("bar",call. = F))$stop("hello")
#> Warning: bar
Created on 2019-08-29 by the reprex package (v0.3.0)
Maybe suppressing_warnings
could also catch and rethrow warnings or errors ? A new name might be preferred then, though suppressing should be the default behavior.
OR we make trying_and_catching()
handle warnings too.
OR we create 2 new tagsinstead : handling_errors()
and handling_warnings()
, but they don't sound so good...
similar to
suppressing_warnings
but the argument given is a list of items where each items is either a regex pattern (in which case we "try"), or a formula in the format"foo" ~ {some_code}
, in which case we tryCatch.some_code
can use.
, which contains the error message.conditions are used in turn until one matches, if none matches we trigger the original error.