Home > Enterprise >  How to provide a useful error message for an incorrect function argument
How to provide a useful error message for an incorrect function argument

Time:10-01

Consider the following toy function

my_function <- function(arg_1, new_arg_2){
  
  string <- paste(arg_1, new_arg_2, sep = " ")
  return(string)
  
}

It has two arguments arg_1 and new_arg_2. They work great.

my_function(arg_1 = "Hello", new_arg_2 = "World!")
[1] "Hello World!"

Presumably though my_function previously had an argument called arg_2, which has since been replaced with new_arg_2.

Running the function using the (old, now nonexistent) argument arg_2 naturally produces an error

my_function(arg_1 = "Hello", arg_2 = "World!")

Error in my_function(arg_1 = "Hello", arg_2 = "World!") :    unused argument (arg_2 = "World!")

What I want is to change this error message so that it says something else, like

"You have supplied arg_2, perhaps you meant to supply new_arg_2"

Somewhat similar to this question except that I want to evaluate the arguments passed to a function inside the function while it's running, rather than getting the expected function names from a non-running function.

How can I do this?

CodePudding user response:

You could add it as an argument and then check if it's used with missing

my_function <- function(arg_1, new_arg_2, arg_2 = NULL){
  if (!missing(arg_2)) {
    stop("\nYou have supplied arg_2, perhaps you meant to supply new_arg_2")
  }
  string <- paste(arg_1, new_arg_2, sep = " ")
  return(string)
  
}

my_function(arg_1 = 1, arg_2 = 2)
#> Error in my_function(arg_1 = 1, arg_2 = 2): 
#> You have supplied arg_2, perhaps you meant to supply new_arg_2

Created on 2021-09-30 by the reprex package (v2.0.1)

There is a package for this called "lifecycle" which is used by tidyverse packages e.g. dplyr to warn users of deprecated arguments and functions.

As mentioned by @Greg in the comments, the "<NA>" would be the name of the package if the function is defined within a package.

library(lifecycle)

my_function <- function(arg_1, new_arg_2, arg_2 = deprecated()){
  if (lifecycle::is_present(arg_2)) {
    lifecycle::deprecate_stop("1.0.8", 
      "my_function(arg_2)",  "my_function(new_arg_2)"
    )
  }
  string <- paste(arg_1, new_arg_2, sep = " ")
  return(string)
  
}

my_function(arg_1 = 1, arg_2 = 2)
#> Error: The `arg_2` argument of `my_function()` was deprecated in <NA> 1.0.8 and is now defunct.
#> Please use the `new_arg_2` argument instead.

Created on 2021-09-30 by the reprex package (v2.0.1)

CodePudding user response:

Modify the function to take any additional arguments, capture the arguments that have been passed, and then test in arg_2 is in them.

my_function <- function(arg_1, new_arg_2, ...){
  args <- as.list(sys.call())
  if ("arg_2" %in% names(args)) {
    stop("You have supplied arg_2, perhaps you meant to supply new_arg_2?")
  }
  string <- paste(arg_1, new_arg_2, sep = " ")
  return(string)
}

> my_function(arg_1 = "Hello", new_arg_2 = "World!")
[1] "Hello World!"

> my_function(arg_1 = "Hello", arg_2 = "World!")
Error in my_function(arg_1 = "Hello", arg_2 = "World!") : 
  You have supplied arg_2, perhaps you meant to supply new_arg_2?
  •  Tags:  
  • r
  • Related