[Rd] stopifnot
Martin Maechler
m@ech|er @end|ng |rom @t@t@m@th@ethz@ch
Wed Mar 6 09:50:18 CET 2019
>>>>> Martin Maechler
>>>>> on Tue, 5 Mar 2019 21:04:08 +0100 writes:
>>>>> Suharto Anggono Suharto Anggono
>>>>> on Tue, 5 Mar 2019 17:29:20 +0000 writes:
>> Another possible shortcut definition:
>> assert <- function(exprs)
>> do.call("stopifnot", list(exprs = substitute(exprs), local = parent.frame()))
> Thank you. I think this is mostly a matter of taste, but I
> liked your version using eval() & substitute() a bit more. For
> me, do.call() is a heavy hammer I only like to use when needed..
> Or would there be advantages of this version?
> Indeed (as you note below) one important consideration is the exact
> message that is produced when one assertion fails.
>> After thinking again, I propose to use
>> stop(simpleError(msg, call = if(p <- sys.parent()) sys.call(p)))
> That would of course be considerably simpler indeed, part "2 a" of these:
>> - It seems that the call is the call of the frame where stopifnot(...) is evaluated. Because that is the correct context, I think it is good.
>> - It is simpler and also works for call that originally comes from stopifnot(exprs=*) .
>> - It allows shortcut ('assert') to have the same call in error message as stopifnot(exprs=*) .
> That may be another good reason in addition to code simplicity.
> I will have to see if this extra simplification does not loose
> more than I'd want.
>> Another thing: Is it intended that
>> do.call("stopifnot", list(exprs = expression()))
>> evaluates each element of the expression object?
> ?? I really don't know. Even though such a case looks
> "unusual" (to say the least), in principle I'd like that
> expressions are evaluated sequentially until the first non-TRUE
> result. With a concrete example, I do like what we have
> currently in unchanged R-devel, but also in R 3.5.x, i.e., in
> the following, not any "NOT GOOD" should pop up:
>> stopifnot(exprs = expression(1==1, 2 < 1, stop("NOT GOOD!\n")))
> Error: 2 < 1 is not TRUE
>> do.call(stopifnot, list(exprs = expression(1==1, 2 < 1, stop("NOT GOOD!\n"))))
> Error in do.call(stopifnot, list(exprs = expression(1 == 1, 2 < 1, cat("NOT GOOD!\n")))) :
> 2 < 1 is not TRUE
>>
> Hmm, it seems I do not understand what you ask above in your
> "Another thing: .."
>> If so, maybe add a case for 'cl', like
>> else if(is.expression(exprs))
>> as.call(c(quote(expression), exprs))
> that seems simple indeed, but at the moment, I cannot see one example
> where it makes a difference ... or then I'm "blind" .. ???
> Best,
> Martin
Some more testing of examples lead me to keep the more
sophisticated "computation" of 'n' for the sys.call(n-1).
Main reason: If one of the expression is not all TRUE, I really
don't want to see the full 'stopifnot(....)' call in the printed
error message.
I do want to encourage that stopifnot() asserts many things
and so its own call should really not be shown.
Also I really wanted to commit something, notably also fixing
the stopifnot(exprs = T) bug, so R-devel (rev >= 76203 ) now
contains a simpler and much faster stopifnot() than previously
[and than the R 3.5.x series].
I agree that the final decisions on getting a call (or not --
which was a very good idea by you!) and which parent's call
should be used may deserve some future tinkering..
Thank you again, Suharto Anggono,
for your contributions to making R better !
Martin
More information about the R-devel
mailing list