From @uh@rto_@nggono @end|ng |rom y@hoo@com  Thu May 30 16:45:22 2019
From: @uh@rto_@nggono @end|ng |rom y@hoo@com (Suharto Anggono Suharto Anggono)
Date: Thu, 30 May 2019 14:45:22 +0000 (UTC)
Subject: [Rd] stopifnot
References: <1923928808.6775475.1559227522953.ref@mail.yahoo.com>
Message-ID: <1923928808.6775475.1559227522953@mail.yahoo.com>

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
@@ -31,7 +31,7 @@
         .Internal(stop(call., .makeMessage(..., domain = domain)))
 }
 
-stopifnot <- function(..., exprs, local = TRUE)
+stopifnot <- function(..., exprs, evaluated = FALSE, local = TRUE)
 {
     n <- ...length()
     if(!missing(exprs)) {
@@ -41,21 +41,19 @@
 		 else if(isFALSE(local)) .GlobalEnv
 		 else if (is.environment(local)) local
 		 else stop("'local' must be TRUE, FALSE or an environment")
-	exprs <- substitute(exprs) # protect from evaluation
-	E1 <- if(is.call(exprs)) exprs[[1]]
+	E1 <- if(!evaluated && is.call(exprs <- substitute(exprs))) exprs[[1]]
 	cl <- if(is.symbol(E1) &&
-		 (E1 == quote(`{`) || E1 == quote(expression))) {
+		 E1 == quote(`{`)) {
 		  exprs[[1]] <- quote(stopifnot) ## --> stopifnot(*, *, ..., *) :
 		  exprs
 	      }
 	      else
 		  as.call(c(quote(stopifnot),
-			    if(is.null(E1) && is.symbol(exprs) &&
-			       is.expression(E1 <- eval(exprs))) # the *name* of an expression
-				as.list(E1)
+			    if(is.expression(exprs))
+				exprs
 			    else
 				as.expression(exprs)
-			    )) # or fail ..
+			    ))
         names(cl) <- NULL
 	return(eval(cl, envir=envir))
     }

--------------------------------------------


 Subject: Re: [Rd] stopifnot
 To: "Martin Maechler" <maechler at stat.math.ethz.ch>
 Cc: r-devel at r-project.org
 Date: Monday, 15 April, 2019, 2:56 AM
 
Also, in current definition of function 'stopifnot' in R 3.6.0 beta or R devel, for 'cl' if 'exprs' is specified, there a case with comment "the *name* of an expression". The intent is allowing
stopifnot(exprs = ee) ,
where variable 'ee' holds an expression object, to work on the expression object.

It is not quite right to use eval(exprs) . It fails when 'stopifnot' is called inside a function, like
f <- function(ee) stopifnot(exprs = ee)
f(expression())

But, how about local=FALSE case? Should the following work?
f <- function(ee) stopifnot(exprs = ee, local = FALSE)
f(expression())

But, why bother making it work, while it is undocumented that 'exprs' argument in 'stopifnot' can be an expression? Well, yes, expectation may be set from the name "exprs" itself or from argument 'exprs' in function 'source' or 'withAutoprint'. Function 'withAutoprint' may be the closest match.

Function 'withAutoprint' has 'evaluated' argument that controls whether work is on value of  'exprs' or on 'exprs' as given. I like the approach.



[Rd] stopifnot
Suharto Anggono Suharto Anggono