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/
On 14/12/2015 11:10 AM, Hadley Wickham 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)I don't think so. We already have all(), so all(x == y) would do what you want. Duncan Murdoch
Hadley wrote> * all.equal is suboptimal because it returns TRUE or a text stringThat 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.
>> 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) > > I don't think so. We already have all(), so all(x == y) would do what you > want.But that recycles, which is what we're trying to avoid here. Hadley -- http://had.co.nz/