I’ve learned that it’s common practice to use optional arguments in function and check them with missing() (e.g. as discussed in SO 22024082)
In this example round0
I recently encountered a similar problem and wanted to solve it in a general way. I think it can be done as shown in the definition of the function g()
below:
f <- function(a = 5, b = 3, c = 2, d = 7) {
if (missing(a)) {print("a is missing.")}
if (missing(b)) {print("b is missing.")}
if (missing(c)) {print("c is missing.")}
if (missing(d)) {print("d is missing.")}
cat(a, b, c, d)
}
g <- function(a = 1, b = 1, c = 1, d = 1) {
args <- as.list(match.call())
args[[1]] <- NULL # remove first list element, it's the function call
do.call(f, args, envir = parent.frame())
}
Here is what we get when calling g()
with different sets of arguments:
> g()
[1] "a is missing."
[1] "b is missing."
[1] "c is missing."
[1] "d is missing."
5 3 2 7
> g(a = 3)
[1] "b is missing."
[1] "c is missing."
[1] "d is missing."
3 3 2 7
> g(b = 10, c = 10)
[1] "a is missing."
[1] "d is missing."
5 10 10 7
You can add to or remove from the args
list if you don't want to hand all arguments to the next function or want to add some. As an example, see the following function g()
that does this in a general way:
g <- function(a = 1, b = 1, c = 1, x = 1, y = 1, z = 1) {
f_args <- c("a", "b", "c") # arguments we want to hand off to function f
# obtain the list of arguments provided
args <- as.list(match.call())
# remove first list element, it's the function call
args[[1]] <- NULL
# remove the arguments that are not listed in f_args
args <- args[na.omit(match(f_args, names(args)))]
# now add argument d, we always want it to be 0:
args <- c(args, list(d = 0))
do.call(f, args, envir = parent.frame())
}
Here is what we get when calling g()
with different sets of arguments:
> g()
[1] "a is missing."
[1] "b is missing."
[1] "c is missing."
5 3 2 0
> g(a = 3)
[1] "b is missing."
[1] "c is missing."
3 3 2 0
> g(b = 10, c = 10)
[1] "a is missing."
5 10 10 0
See this answer for additional information on do.call()
.