1

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?

Greg
  • 3,570
  • 5
  • 18
  • 31

2 Answers2

3

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)

IceCreamToucan
  • 28,083
  • 2
  • 22
  • 38
  • Looking at the lifecycle vignette I think the would populate with the package name if used inside a package function https://lifecycle.r-lib.org/articles/communicate.html – Greg Sep 30 '21 at 16:50
  • Oh, makes sense, thanks. Should have known that. Thinking about it now I recall "deprecated in dplyr 1.0.0" being in some messages. – IceCreamToucan Sep 30 '21 at 16:52
2

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?
cazman
  • 1,452
  • 1
  • 4
  • 11