Search code examples
rerror-handlingbooleanis-empty

Why does empty logical vector pass the stopifnot() check?


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?


Solution

  • Other answers cover the practical reasons why stopifnot behaves the way it does; but I agree with Karolis that the thread linked by Henrik adds the real explanation of why this is the case:

    As author stopifnot(), I do agree with [OP]'s "gut feeling" [...] that stopifnot(dim(x) == c(3,4)) [...][should] stop in the case where x is a simple vector instead of a matrix/data.frame/... with dimensions c(3,4) ... but [...] the gut feeling is wrong because of the fundamental lemma of logic: [...]

    "All statements about elements of the empty set are true"

    Martin Maechler, ETH Zurich

    Also, [...], any() is to "|" what sum() is to "+" and what all() is to "&" and prod() is to "*". All the operators have an identity element, namely FALSE, 0, TRUE, and 1 respectively, and the generic convention is that for an empty vector, we return the identity element, for the reason given above.

    Peter D.