Today I found that some of my stopifnot()
tests are failing because the passed arguments evaluate to empty logical vectors.
Here is an example:
stopifnot(iris$nosuchcolumn == 2) # passes without error
This is very unintuitive and seems to contradict a few other behaviours. Consider:
isTRUE(logical())
> FALSE
stopifnot(logical())
# passes
So stopifnot()
passes even when this argument is not TRUE
.
But furthermore, the behaviour of the above is different with different types of empty vectors.
isTRUE(numeric())
> FALSE
stopifnot(numeric())
# Error: numeric() are not all TRUE
Is there some logic to the above, or should this be considered a bug?
The comments by akrun and r2evans are spot on.
However, to give details on why specifically this happens and why you're confused vs. isTRUE()
behavior, note that stopifnot()
checks for three things; the check is (where r
is the result of the expression you pass):
if (!(is.logical(r) && !anyNA(r) && all(r)))
So, let's take a look:
is.logical(logical())
# [1] TRUE
!anyNA(logical())
# [1] TRUE
all(logical())
# [1] TRUE
is.logical(numeric())
# [1] FALSE
!anyNA(numeric())
# [1] TRUE
all(numeric())
# [1] TRUE
So, the only reason why logical()
passes while numeric()
fails is because numeric()
is not "logical," as suggested by akrun. For this reason, you should avoid checks that may result in logical vectors of length 0, as suggested by r2evans.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With