[R] stopifnot with logical(0)

William Dunlap wdunlap at tibco.com
Mon Dec 14 17:31:29 CET 2015


Hadley wrote
> * all.equal is suboptimal because it returns TRUE or a text string

That feature works ok with stopifnot():
  > stopifnot(all.equal("one", 1))
  Error: all.equal("one", 1) are not all TRUE
and I suppose stopifnot could be enhanced to print the text strings that
all.equal() returns so the user has a better idea of what went wront.

I find that all.equal's comparing of names gets in the way of the intent
of stopifnot
  > stopifnot(all.equal(1:2, c(X=1,Y=2)))
  Error: all.equal(1:2, c(X = 1, Y = 2)) is not TRUE

When we use things like all.equal() or new operators that do
non-recycycling binary operations we may make things simpler
for the programmer, but harder for the user.  I think the user would
rather see a specific message about what is wrong rather than a
note that an obscure function did not return TRUE.
    > f <- function(x) {
         stopifnot(length(x)==1, x>0)
         seq_len(x)
      }
    > f(1:3)
    Error: length(x) == 1 is not TRUE
    > f(-4)
    Error: x > 0 is not TRUE
    > f(4)
    [1] 1 2 3 4

Another step in this direction is to change the call to stop() in stopifnot
from what I assume is
    stop(message, call.=FALSE)
to
    stop(simpleError(message, sys.call(-1)))
so the error message included where error was:
    > f(-1)
    Error in f(-1) : x > 0 is not TRUE
(This is Bug 16188.)

Bill Dunlap
TIBCO Software
wdunlap tibco.com


On Mon, Dec 14, 2015 at 8:10 AM, Hadley Wickham <h.wickham at gmail.com> wrote:
> On Sat, Dec 12, 2015 at 1:51 PM, Martin Maechler
> <maechler at stat.math.ethz.ch> wrote:
>>>>>>> Hadley Wickham <h.wickham at gmail.com>
>>>>>>>     on Sat, 12 Dec 2015 08:08:54 -0600 writes:
>>
>>     > 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)))
>>
>> You are right "in theory"  but practice is less easy:
>> identical() tends to be  too subtle for many users ... even
>> yourself (;-), not really of course!),  Hadley, in the above case:
>>
>> Your stopifnot() would *always* stop, i.e., signal an error
>> because typically all dim() methods return integer, and c(3,4)
>> is double.
>> So, if even Hadley gets it wrong so easily, I wonder if its good
>> to advertize to always use  identical() in such cases.
>> I indeed would quite often use identical() in such tests, and
>> you'd too and would quickly find and fix the "trap" of course..
>> So you are mostly right also in my opinion...
>
> Ooops, yes - but you would discover this pretty quickly if you weren't
> coding in a email client ;)
>
> I wonder if R is missing an equality operator for this case. Currently:
>
> * == is suboptimal because it's vectorised
> * all.equal is suboptimal because it returns TRUE or a text string
> * identical is suboptimal because it doesn't do common coercions
>
> Do we need another function (equals()?) that uses the same coercion
> rules as == but isn't vectorised? (Like == it would only work with
> vectors, so you'd still need identical() for (e.g.) comparing
> environments)
>
> Hadley
>
> --
> http://had.co.nz/
>
> ______________________________________________
> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.



More information about the R-help mailing list