[R] stopifnot with logical(0)

Henrik Bengtsson henrik.bengtsson at gmail.com
Sat Dec 12 16:57:38 CET 2015


On Sat, Dec 12, 2015 at 6:08 AM, Hadley Wickham <h.wickham at gmail.com> wrote:
> On Sat, Dec 12, 2015 at 3:54 AM, Martin Maechler
> <maechler at stat.math.ethz.ch> wrote:
>>>>>>> Henrik Bengtsson <henrik.bengtsson at gmail.com>
>>>>>>>     on Fri, 11 Dec 2015 08:20:55 -0800 writes:
>>
>>     > On Fri, Dec 11, 2015 at 8:10 AM, David Winsemius <dwinsemius at comcast.net> wrote:
>>     >>
>>     >>> On Dec 11, 2015, at 5:38 AM, Dario Beraldi <dario.beraldi at gmail.com> wrote:
>>     >>>
>>     >>> Hi All,
>>     >>>
>>     >>> I'd like to understand the reason why stopifnot(logical(0) == x) doesn't
>>     >>> (never?) throw an exception, at least in these cases:
>>     >>
>>     >> The usual way to test for a length-0 logical object is to use length():
>>     >>
>>     >> x <- logical(0)
>>     >>
>>     >> stopifnot( !length(x) & mode(x)=="logical" )
>>
>>     > I found
>>
>>     > stopifnot(!length(x), mode(x) == "logical")
>>
>>     > more helpful when troubleshooting, because it will tell you whether
>>     > it's !length(x) or mode(x) == "logical" that is FALSE.  It's as if you
>>     > wrote:
>>
>>     > stopifnot(!length(x))
>>     > stopifnot(mode(x) == "logical")
>>
>>     > /Henrik
>>
>> Yes, indeed, thank you Henrik  --- and Jeff Newmiller who's nice
>> humorous reply added other relevant points.
>>
>> As author stopifnot(), I do agree with Dario's  "gut feeling"
>> that stopifnot()  "somehow ought to do the right thing"
>> in cases such as
>>
>>    stopifnot(dim(x) == c(3,4))
>>
>> which is really subtle version of his cases
>> {But the gut feeling is wrong, as I argue from now on}.
>
> Personally, I think the problem there is that people forget that == is
> vectorised, and for a non-vectorised equality check you really should
> use identical:
>
> stopifnot(identical(dim(x), c(3,4)))

Kids, this one of the rare cases where you should not listen to Hadley
;)  Because,

> x <- matrix(1:12, nrow=3, ncol=4)
> dim(x)
[1] 3 4
> identical(dim(x), c(3,4))
[1] FALSE

Why, because:

> storage.mode(dim(x))
[1] "integer"
> storage.mode(c(3,4))
[1] "double"

My rule of thumb is that identical() is awesome, but you really have
to know the inner bits and pieces (*).  When in doubt, use
all.equal(), e.g.

> all.equal(dim(x), c(3,4))
[1] TRUE

Related to Hadley's point, is that using all(x == y) is risky because
R loops of one of the two vectors if one is longer than the other,
e.g.

> all(dim(x) == c(3,4))
[1] TRUE
> all(dim(x) == c(3,4,3,4))
[1] TRUE
> all(dim(x) == c(3,4,3,4,3,4))
[1] TRUE

so one really need to check the lengths as well, e.g.

> all(length(dim(x)) == length(c(3,4)), dim(x) == c(3,4))
[1] TRUE


(*) ADVANCED: I would say its risky to use:

> identical(dim(x), c(3L,4L))
[1] TRUE

because, who knows, in a future version of R we might see
matrices/arrays that support dimensions longer than
.Machine$integer.max which in case dimensions may be stored as
doubles.  This is what we already have for very long vectors today,
cf. help("length").

Henrik

>
> Hadley
>
> --
> http://had.co.nz/



More information about the R-help mailing list