The stop_if()
, warn_if()
and
message_if()
are easy to use functions that send an error,
a warning or a message if a condition is met. Each function has its
counterpart with _not
that returns a message if the
condition is not met.
stop_if_not()
is quite the same as
assert_that()
from the {assertthat} package, except that it
can takes mappers. It is not the same as base stopifnot()
,
as it doesn’t take a list of expression.
These functions are also flexible as you can pass base predicates (is.numeric, is.character…), a custom predicate built with mappers, or even your own predicate function.
You can either choose a custom message or just let the built-in messages be printed:
x <- 12
# Stop if .x is numeric
stop_if(
.x = x,
.p = is.numeric
)
#> Error: Test `is.numeric` on `x` returned an error.
y <- "20"
# stop if .x is not numeric
stop_if_not(
.x = y,
.p = is.numeric,
msg = "y should be numeric"
)
#> Error: y should be numeric
a <- "this is not numeric"
# Warn if .x is charcter
warn_if(
.x = a,
.p = is.character
)
#> Warning: Test `is.character` on `a` returned a warning.
b <- 20
# Warn if .x is not equal to 10
warn_if_not(
.x = b,
.p = ~ .x == 10,
msg = "b should be 10"
)
#> Warning: b should be 10
c <- "a"
# Message if c is a character
message_if(
.x = c,
.p = is.character,
msg = "You entered a character element"
)
#> You entered a character element
# Build more complex predicates
d <- 100
message_if(
.x = d,
.p = ~ sqrt(.x) < 42,
msg = "The square root of your element must be more than 42"
)
#> The square root of your element must be more than 42
# Or, if you're kind of old school, you can still pass classic functions
e <- 30
message_if(
.x = e,
.p = function(vec) {
return(sqrt(vec) < 42)
},
msg = "The square root of your element must be more than 42"
)
#> The square root of your element must be more than 42
If you need to call a function that takes no argument at
.p
(like curl::has_internet()
), use this
function as .x
.
stop_if(.x = curl::has_internet(), msg = "You shouldn't have internet to do that")
#> Error: You shouldn't have internet to do that
warn_if(
.x = curl::has_internet(),
msg = "You shouldn't have internet to do that"
)
#> Warning: You shouldn't have internet to do that
message_if(
.x = curl::has_internet(),
msg = "Huray, you have internet \\o/"
)
#> Huray, you have internet \o/
If you don’t specify a .p
, the default test is
isTRUE()
.
That can come really handy inside a function:
my_fun <- function(x) {
stop_if_not(
.x = curl::has_internet(),
msg = "You should have internet to do that"
)
warn_if_not(
x,
is.character,
msg = "x is not a character vector. The output may not be what you're expecting."
)
paste(x, "is the value.")
}
my_fun(head(iris))
#> Warning: x is not a character vector. The output may not be what you're
#> expecting.
#> [1] "c(5.1, 4.9, 4.7, 4.6, 5, 5.4) is the value."
#> [2] "c(3.5, 3, 3.2, 3.1, 3.6, 3.9) is the value."
#> [3] "c(1.4, 1.4, 1.3, 1.5, 1.4, 1.7) is the value."
#> [4] "c(0.2, 0.2, 0.2, 0.2, 0.2, 0.4) is the value."
#> [5] "c(1, 1, 1, 1, 1, 1) is the value."
stop_if()
, warn_if()
and
message_if()
all have complementary tests with
_all
, _any
and _none
, which
combine the if_*
and the warn_*
,
stop_*
and message_*
seen before. They take a
list as first argument, and a predicate. They test if any, all or none
of the elements validate the predicate.
stop_if_any(iris, is.factor, msg = "Factors here. This might be due to stringsAsFactors.")
#> Error: Factors here. This might be due to stringsAsFactors.
warn_if_none(1:10, ~ .x < 0, msg = "You need to have at least one number under zero.")
#> Warning: You need to have at least one number under zero.
message_if_all(1:100, is.numeric, msg = "That makes a lot of numbers.")
#> That makes a lot of numbers.