[Rd] stopifnot
Martin Maechler
m@ech|er @end|ng |rom @t@t@m@th@ethz@ch
Thu Jun 6 16:06:53 CEST 2019
>>>>> Martin Maechler
>>>>> on Mon, 3 Jun 2019 18:14:15 +0200 writes:
>>>>> Suharto Anggono Suharto Anggono
>>>>> on Thu, 30 May 2019 14:45:22 +0000 writes:
>>>>> Suharto Anggono Suharto Anggono
>>>>> on Thu, 30 May 2019 14:45:22 +0000 writes:
>> Here is a patch to function 'stopifnot' that adds 'evaluated' argument and makes 'exprs' argument in 'stopifnot' like 'exprs' argument in 'withAutoprint'.
>> --- stop.R 2019-05-30 14:01:15.282197286 +0000
>> +++ stop_new.R 2019-05-30 14:01:51.372187466 +0000
> [..........]
> Thank you, Suharto.
> I've looked at the patch and tested it a bit, and also (re)read
> your April 15 remarks (cited below). I now agree that my hacks to
> enable dealing with "language objects" (typically class
> 'expression') 'exprs' has remained hackish and hence not
> working in all cases, and that it may be a better idea to add
> a new logical argument (as in other functions) which has to be
> "switched" and then leads somewhat simpler and more robust code.
> OTOH, of course, this is an API change would typically not go into the R
> 3.6.x series ... and I have no idea if it would affect much more
> than R's own tests/reg-tests-* ...
> Even though the argument name 'evaluated' was chosen for
> withAutoprint(), I don't find it a very good name anymore, and -
> if the change should happen - would probably prefer something
> like 'is.language' or 'expr.is.language' or similar..
> Could we get any other readers' opinions ?
[none ..]
In the mean time, I've seen a nicer solution: If have to add
yet another argument to stopifnot() to make this cleaner, I'm
now pretty sure we should rather use that new argument to pass
an "expression-alike" object instead of unevaluated expressions.
I'm calling it `exprObject` for now (and ditch the `evaluated=FALSE`).
With that the new code becomes even cleaner and easier to understand:
stopifnot <- function(..., exprs, exprObject, local = TRUE)
{
n <- ...length()
if((has.e <- !missing(exprs)) || !missing(exprObject)) {
if(n || (has.e && !missing(exprObject)))
stop("Only one of 'exprs', 'exprObject' or unnamed expressions, not more")
envir <- if (isTRUE(local)) parent.frame()
else if(isFALSE(local)) .GlobalEnv
else if (is.environment(local)) local
else stop("'local' must be TRUE, FALSE or an environment")
E1 <- if(has.e && is.call(exprs <- substitute(exprs))) exprs[[1]]
cl <- if(is.symbol(E1) &&
E1 == quote(`{`)) {
exprs[[1]] <- quote(stopifnot) ## --> stopifnot(*, *, ..., *) :
exprs
}
else
as.call(c(quote(stopifnot),
if(!has.e) exprObject else as.expression(exprs)))
names(cl) <- NULL
return(eval(cl, envir=envir))
}
## else use '...' (and not 'exprs') :
[............ code unchanged from here to the end .. ............]
[............ code unchanged from here to the end .. ............]
}
More information about the R-devel
mailing list