From davison at uchicago.edu  Wed Mar  1 22:44:52 2006
From: davison at uchicago.edu (Dan Davison)
Date: Wed, 1 Mar 2006 15:44:52 -0600 (CST)
Subject: [Rd] stopifnot() suggestion
Message-ID: <Pine.GSO.4.62.0603011507180.13700@harper.uchicago.edu>

If an expression is passed to stopifnot() which contains missing values, 
then the resulting error message is somewhat baffling until you are used 
to it, e.g.

> x <- y <- rep(TRUE, 10)
> y[7] <- NA
> stopifnot(x, y)
Error in if (!(is.logical(r <- eval(ll[[i]])) && all(r))) 
stop(paste(deparse(mc[[i +  :
 	missing value where TRUE/FALSE needed

A minor change to stopifnot() produces the following behaviour:

> stopifnot(x, y)
Error in stopifnot(x, y) : y contains missing values

My attempt at a suitable modification follows, and below that the original 
function definition. Is a change along these lines appropriate?

## Altered version

stopifnot <- function (...) {
     n <- length(ll <- list(...))
     if (n == 0)
         return(invisible())
     mc <- match.call()
     for (i in 1:n) {
         if(any(is.na(r <- eval(ll[[i]])))) stop(paste(deparse(mc[[i + 1]])), " contains missing values")
         if (!(is.logical(r) && all(r)))
             stop(paste(deparse(mc[[i + 1]]), "is not TRUE"), call. = FALSE)
     }
}


## from R-2.1.1/src/library/base/R/stop.R

stopifnot <- function(...)
{
     n <- length(ll <- list(...))
     if(n == 0)
         return(invisible())
     mc <- match.call()
     for(i in 1:n)
         if(!(is.logical(r <- eval(ll[[i]])) && all(r)))
             stop(paste(deparse(mc[[i+1]]), "is not TRUE"), call. = FALSE)
}


Thanks,

Dan


> version
          _
platform i386-pc-linux-gnu
arch     i386
os       linux-gnu
system   i386, linux-gnu
status
major    2
minor    2.0
year     2005
month    10
day      06
svn rev  35749
language R

----------
Dan Davison
Committee on Evolutionary Biology
University of Chicago, U.S.A.



[Rd] stopifnot() suggestion
Dan Davison