R语言:判断参数匹配函数的实现及可变参数适配问题
...) Your original args_match function works well for functions without ... because match.call throws an error when you pass unrecognized named arguments. However, it fails for functions with ... for two key reasons:
match.calldoesn't check if required arguments (those without default values) are missing.- Any extra arguments get absorbed by
..., somatch.callwon't throw an error even if critical required parameters are omitted.
To fix this, we can use rlang::call_standardise—this function not only validates that arguments match the function's formal parameters but also ensures all required arguments are provided. It standardizes the call and throws errors specifically for parameter-related issues like missing required args or unrecognized arguments (when no ... is present).
Updated Implementation
library(rlang) args_match <- function(fun, ...) { # Construct the call object from the input function and arguments fun_call <- call(deparse(substitute(fun)), ...) # Attempt to standardize the call; catch parameter-matching errors tryCatch( { call_standardise(fun_call, fun = fun) TRUE }, error = function(e) { # Return FALSE for any parameter validation failure FALSE } ) }
Test Cases
First, confirm the original examples still behave correctly:
# Returns FALSE (fivenum has no 'y' argument and no ...) args_match(fivenum, y = 1:10) #> [1] FALSE # Returns TRUE (matches fivenum's required 'x' argument) args_match(fivenum, x = 1:10) #> [1] TRUE
Now test functions with ... to verify the fix:
# Define a custom function with a required argument and ... my_fun <- function(a, ...) { a } # Missing required 'a' → returns FALSE args_match(my_fun) #> [1] FALSE # Valid call with 'a' → returns TRUE args_match(my_fun, a = 5) #> [1] TRUE # Valid call with extra args absorbed by ... → returns TRUE args_match(my_fun, a = 5, b = 10) #> [1] TRUE # Missing 'a' even with extra args → returns FALSE args_match(my_fun, b = 10) #> [1] FALSE
Test with a built-in function that includes ...:
# Missing required 'x' → returns FALSE args_match(mean) #> [1] FALSE # Valid call with 'x' → returns TRUE args_match(mean, x = 1:10) #> [1] TRUE # Valid call with extra args (absorbed by ...) → returns TRUE args_match(mean, x = 1:10, na.rm = TRUE, foo = "test") #> [1] TRUE
Why This Works
call_standardise addresses the gaps in the original implementation by validating two critical aspects of function calls:
- Unrecognized arguments: If you pass a named argument that doesn't exist in the function's formal parameters and the function has no
..., it throws an error. - Missing required arguments: If a parameter has no default value and isn't provided in the call, it throws an error.
Unlike match.call, it doesn't overlook missing required arguments—this is the core fix that makes it work for functions with ....
内容的提问来源于stack exchange,提问作者user3603486

