If I include stop() within an R function to teminate the function given a particular condition, the error handling behaviour of RStudio appears to be different to built-in error handling.
Terminating the function using stop sends RStudio into debugging mode whereas an error generated by (for example not giving an input to the function) doesn’t.
I would like to write the function so the behaviour is the same in both cases, regardless of the debug settings in RStudio.
Here is an example function which converts mass from grams to ounces.
I want to terminate the function if the input is a negative mass, with a message that you should only use a positive mass.
mass_convert <- function(mass) {
if (mass < 0) {
stop ("Please input positive mass")
}
mass * 0.03527396
}
In the RStudio settings in the toolbar: Debug | On Error | is set to “Break in Code”.
RStudio debugging settings
If I run the following:
mass_convert(-1)
I get the expected error message
Error in mass_convert(-1) : Please input positive mass Called from: mass_convert(-1)
but RStudio goes into debug mode.
If I instead run:
mass_convert()
I still get an error message:
Error in mass_convert() : argument "mass" is missing, with no default
but this time RStudio does not go into debug mode.
I have two questions following this:
-
What is the reason behind the two different behaviours?
-
How can I get the if statement to terminate the function in a similar manner to if no input is given, while keeping the RStudio settings for debugging as “Break in Code”. I.e. I want the function to terminate if given a negative mass, but there is no need to go into debug mode as the message describes what the problem is.
One option could be to use warning() instead and put the function evaluation after an ‘else’ statement:
mass_convert <- function(mass) {
if (mass < 0) {
warning ("Please input positive mass")
} else mass * 0.03527396
}
but it feels like there should be a way to do this with error() instead. Or, am I using error in the wrong way?
Pratorum is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
2
RStudio’s built-in debugger ignores certain kinds of errors, apparently including this one. You can read about this in Posit’s guide to debugging in Rstudio, which explains that:
To keep the the debugger from being invoked whenever any error anywhere happens, RStudio does not invoke the debugger if it looks like none of your own code is on the stack. If you find that this is excluding an error you want to catch, go to Tools -> Global Options and uncheck “Use debug error handler only when my code contains errors”.
However unchecking that box was not sufficient to break on the error in your example. In order to get that to happen, I had to follow their subsequent advice:
If you really want to invoke the debugger on every error, always, this will do the job:
options(error = browser)
But that took me into a debugging environment that I couldn’t leave, because I was apparently debugging in the ‘top level’ (i.e not within a function). So don’t do that either.
With regards to your second question, I would advise against ‘overwriting’ this very low-level error with an error message of your own. There is already a system for throwing errors when functions are missing required arguments, and redesigning it for one function will lead to less predictable code. But, if you really wanted to, you could use rlang
‘s is_missing()
:
library(rlang)
foo <- function(x){
if(is_missing(x)) stop("X is missing")
x * 2
}
foo(1)
#> [1] 2
foo()
#> Error in foo(): X is missing
Created on 2024-09-25 with reprex v2.1.1
6
EDIT: Supplementend error=NULL
.
I want to terminate the function if the input is a negative mass, with a message that you should only use a positive mass.
I suspect your a looking for
mass_convert = (mass) {
if(any(mass < 0, na.rm=TRUE)) {
cat("Please input positive mass!")
opt = options(show.error.messages=FALSE, error=NULL)
on.exit(options(opt))
stop()
}
mass * 0.03527396
}
where the clever part is stolen from here, giving
> mass_convert(c(1, 3, -1, NA))
Please input positive mass!
> mass_convert(c(1, 3, NA))
[1] 0.03527396 0.10582188 NA
1