我希望能够有一种方法来检查所有参数,而不是在调用R中的函数时指定默认值。这对我来说似乎是一件明智的事情,因为它避免了函数在以后失败(当发现一个值丢失时,可能经过大量处理)。
完成此任务的一种方法是为每个参数编写一个if (missing(arg))
语句,但这需要保持函数的参数和上述语句相互一致,所以我正在寻找一个更好的解决方案。
目前我使用以下功能,这在大多数情况下有效,但不是全部。
# check for required arguments by getting arguments for the
# definition of the calling function and comparing to the arguments
# in the function call
check_required_args <- function () {
def <- sys.function(-1)
f_args <- formals(def)
f_args <- f_args[sapply(f_args, is.name)] # remove arguments with defaults
f_args <- names(f_args)
f_args <- f_args[f_args != '...'] # remove ellipsis argument if present
call <- match.call(definition=def, call=sys.call(-1))
f_name <- call[1]
c_args <- names(as.list(call[-1]))
for(n in f_args) {
if (!n %in% c_args) {
stop("Argument '", n, "' missing from call to function ",
f_name, "()", call.=FALSE)
}
}
}
f <- function(a, b, c=2) check_required_args()
f(a=1) # should fail (missing argument b)
f(2, 3) # should work
f(2, c=5) # should fail (missing argument b)
f(2, 3, 4) # should work
f <- function(a, b, ...) f2(a, b, ...)
f2 <- function(a, b, c, ...) check_required_args()
f2(a=1, b=2, c=3) # should work
f2(a=1, b=2) # should fail (missing argument c for function f2)
f(a=1, b=2, c=3) # should work
f(a=1, b=2) # should fail (missing argument c for function f2)
是否可以改进此功能以适用于所有这些情况?如果没有,是否有更合适的解决方案来执行此检查?
答案 0 :(得分:3)
也许这个?
check_required_args <- function (fun = sys.function(-1), ncall = 3) {
f_args <- formals(fun)
f_args <- f_args[vapply(f_args, is.symbol, FUN.VALUE = TRUE)]
f_args <- names(f_args)
f_args <- setdiff(f_args, "...")
test <- vapply(f_args,
function(x) missingArg(as.name(x), envir = parent.frame(ncall), eval = TRUE),
FUN.VALUE = TRUE)
stopifnot(!any(test))
return(invisible(NULL))
}
f <- function(a, b, c=2) {
check_required_args()
return("Hello!")
}
f(a=1) # should fail (missing argument b)
#Error: !any(test) is not TRUE
f(2, 3) # should work
#[1] "Hello!"
f(2, c=5) # should fail (missing argument b)
# Error: !any(test) is not TRUE
f(2, 3, 4) # should work
#[1] "Hello!"
x <- 1
f(a=x, 3)
#[1] "Hello!"
f <- function(a, b, ...) f2(a, b, ...)
f2 <- function(a, b, c, ...) {
check_required_args()
return("Hello!")
}
f2(a=1, b=2, c=3) # should work
#[1] "Hello!"
f2(a=1, b=2) # should fail (missing argument c for function f2)
#Error: !any(test) is not TRUE
f(a=1, b=2, c=3) # should work
#[1] "Hello!"
f(a=1, b=2) # should fail (missing argument c for function f2)
#Error: !any(test) is not TRUE
您可能希望使用get
来检查是否存在:
check_required_args <- function (fun = sys.function(-1), ncall = 3) {
f_args <- formals(fun)
f_args <- f_args[vapply(f_args, is.symbol, FUN.VALUE=TRUE)]
f_args <- names(f_args)
f_args <- setdiff(f_args, "...")
test <- lapply(f_args,
function(x) {
get(x, envir = parent.frame(ncall), inherits = TRUE)
return(NULL)
})
#possibly use a for loop instead
#wrap in tryCatch for customized error messages
}
f <- function(a, b, ...) f2(a, b, ...)
f2 <- function(a, b, c, ...) {
check_required_args()
return("Hello!")
}
f(c=2)
#Error in get(x, envir = parent.frame(ncall), inherits = TRUE) :
# argument "a" is missing, with no default
如果您不想签入封闭的框架,请设置inherits = FALSE
。