r-studio: is there a "strict mode"?
There is no "strict" mode, especially for functions that use ellipses to pass parameters through to other functions. Here sum
doesn't care about parameter names. For example
sum(1:4, whatever=4)
sum(1:4, 4)
run just fine and both return the same value. Rather than using such functions, you could write your own wrapper functions that more aggressively check parameter values. Here's a "safe" version of sum
safe_sum <- function(...) {
cx <- match.call()
cn <- names(cx)[-1]
if (!is.null(cn)) {
bad_names <- cn[cn!="" & cn!="na.rm"]
if(length(bad_names)) {
stop(paste("unexpected named parameter:", paste(bad_names, collapse=", ")))
}
}
cx[[1]] <- quote(sum)
eval(cx)
}
safe_sum(1:5, rm.na=TRUE)
# Error in safe_sum(1:5, rm.na = TRUE) : unexpected named parameter: rm.na
Which you can use with tapply
set.seed(10)
CPS <- data.frame(
C = sample(c("S","T"), 50, replace=TRUE),
M = sample(LETTERS[1:4], 50, replace=TRUE)
)
sort(tapply(CPS$C == "S", CPS$M, safe_sum , na.rm=TRUE))
# D A B C
# 3 5 8 9
sort(tapply(CPS$C == "S", CPS$M, safe_sum , rm.na=TRUE))
# Error in FUN(X[[i]], ...) : unexpected named parameter: rm.na
If you wanted to do this with other functions, you could create a factory to check all parameter names. Here's such a function
check_match_names <- function(fun) {
args <- formalArgs(args(sum))
args <- args[args!="..."]
function(...) {
cx <- match.call()
cn <- names(cx)[-1]
if (!is.null(cn)) {
bad_names <- cn[cn!="" & !(cn %in% args)]
if(length(bad_names)) {
stop(paste("unexpected named parameter:", paste(bad_names, collapse=", ")))
}
}
cx[[1]] <- fun
eval.parent(cx)
}
}
And then you would create your function with
safe_sum <- check_match_names(sum)
You can also use the package {ellipsis} to make a safe_sum
function :
safe_sum <- function(..., na.rm = FALSE) {
ellipsis::check_dots_unnamed()
sum(..., na.rm)
}
CPS<- data.frame(C = NA ,M = "A")
sort(tapply(CPS$C == "S", CPS$M, safe_sum, rm.na=TRUE))
#> Error: 1 components of `...` had unexpected names.
#>
#> We detected these problematic arguments:
#> * `rm.na`
#>
#> Did you misspecify an argument?
Created on 2020-09-28 by the reprex package (v0.3.0)