问题
I think my question can be made quite generic and simple, so that I will not give the concrete function that I am trying to make.
I have a function that changes its behaviour according to its first argument:
example <- function(arg1 = T,
arg2 = NULL,
arg3,
...) {
if (arg1 != T) {
final <- bind_rows(arg2)
} else{
list1 <- list(...)
final <- bind_rows(list1, arg3)
}
return(final)
}
My issue is that if I run example(arg1 = T, arg3 = x, c(A,B), c(C,D)), considering that the user of my function probably won't write out anything for arg2, I have a problem. c(A,B) ends up not being considered the first element of list1 (I guess it is assigned to arg2 and then goes unused in the function) and I have bind_rows(c(C,D), x) as the output, instead of bind_rows(c(A,B), c(C,D), x).
How can this be fixed, considering that the function is not for personal use, but for a larger package?
回答1:
put arg2 in ...
example <- function(arg1 = T,
arg3,
...) {
args <- list(...)
if (is.null(args$arg2) & arg1==F) {stop("arg2 needed when arg1==F")}
if (arg1 != T) {
final <- list(arg2)
} else{
list1 <- list(...)
final <- list(list1, arg3)
}
return(final)
}
回答2:
Weirdly enough, you can switch the order of your arguments and have those dots first.
library(dplyr)
#> Warning: package 'dplyr' was built under R version 3.6.3
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
ex <- function(...,
arg1 = T,
arg2 = NULL,
arg3) {
if (arg1 != T) {
final <- bind_rows(arg2)
} else{
list1 <- list(...)
final <- bind_rows(list1, arg3)
}
return(final)
}
ex(arg1 = T, arg3 = iris[1, ], iris[2, ], iris[3, ])
#> Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#> 1 4.9 3.0 1.4 0.2 setosa
#> 2 4.7 3.2 1.3 0.2 setosa
#> 3 5.1 3.5 1.4 0.2 setosa
Created on 2020-06-10 by the reprex package (v0.3.0)
I don't know if this is advised (and I'm hesitant to suggest this), but it does solve your issue using the code you've provided. The answer proposed by @Waldi is a much better solution to your problem.
来源:https://stackoverflow.com/questions/62296913/running-a-function-with-multiple-arguments-when-an-argument-is-not-used