Build Status

ArgumentCheck

ArgumentCheck has been deprecated!!

If you've been using ArgumentCheck, I apologize, but I will no longer be maintaining this package. checkmate 1.6.3 (2016-10-23) introduced assert collections which allow error messages to be collected and reported together. This means that checkmate now provides the core feature of ArgumentCheck and does argument checking better. It really is a much better package, and I encourage you to switch.

If you need assistance migrating from ArgumentCheck to checkmate, please file an issue and I will do my best to assist you. My apologies for the inconvenience, but your code will be better for the change.

Simple Tools for Facilitating Informative Parameter Checks in R Functions.

The typical process of checking arguments in functions is iterative. In this process, an error may be returned and the user may fix it only to receive another error on a different argument. ArgumentCheck facilitates a more helpful way to perform argument checks allowing the programmer to run all of the checks and then return all of the errors and warnings in a single message.

Iterative Errors

Under the "Fail Early, Fail Often" philosophy, programmers are encouraged to terminate functions with an error when they first encounter an error. With Fail Early Fail Often, one might program a function to calculate the volume of a cylinder as

cylinder.volume <- function(height, radius)
{
  if (height < 0) stop("'height' must be >= 0")
  if (radius < 0) stop("'radius' must be >= 0")
  pi * radius^2 * height  
}

In this function, passing a negative value to either height or radius will cause an error.

> cylinder.volume(-3, -3)

Error in cylinder.volume(-3, -3) : 'height' must be >= 0

As expected, the function failed when it noticed that height was a negative value, but it never noticed the lurking problem that volume was also negative.

A modified philosophy of "Fail Early, Fail Often, Fail All At Once" might inspire the following function.

cylinder.volume_improved <- function(height, radius)
{
  #* Establish a new 'ArgCheck' object
  Check <- ArgumentCheck::newArgCheck()
  
  #* Add an error if height < 0
  if (height < 0) 
    ArgumentCheck::addError(
      msg = "'height' must be >= 0",
      argcheck = Check
    )
  
  #* Add an error if radius < 0
  if (radius < 0)
    ArgumentCheck::addError(
      msg = "'radius' must be >= 0",
      argcheck = Check
    )
  
  #* Return errors and warnings (if any)
  ArgumentCheck::finishArgCheck(Check)
  
  pi * radius^2 * height 
}

> cylinder.volume_improved(-3, -3)

Error: 
cylinder.volume_improved(-3, -3)
1: 'height' must be >= 0
2: 'radius' must be >= 0 

While the code is noticeably longer, it has the advantage of returning both errors together.

ArgumentCheck uses an environment to store error and warning messages. This environment is created within the function. As an environment, carefully constructed nested functions can use a common environment to pass any number of warnings and errors to the user the first time finishArgCheck is encountered.

For the trivial example used here, the difference in performance is negligible. Additional efforts are underway to determine the performance cost of the additional code used when implementing ArgumentCheck.

system.time(cylinder.volume(-3, -3))

system.time(cylinder.volume_improved(-3, -3))