>>>>> 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 ______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel