Мы можем обернуть вызов функции в try
, а затем, если он потерпит неудачу, выполнить некоторую гимнастику, чтобы проанализировать исходный вызов и формальные выражения и определить, что могло пойти не так.
Собрать все в одинфункция, которую мы получаем:
with_friendly_dot_error <- function(fun){
fiendly_fun <- fun
body(fiendly_fun) <- substitute({
MC <- match.call()
MC[[1]] <- quote(fun)
res <- try(eval.parent(MC),silent = TRUE)
if(inherits(res,"try-error")){
frmls <- setdiff(names(formals()),"...")
dot_names <- names(eval(substitute(alist(...))))
candidates <- intersect(paste0(".",dot_names), frmls)
stop(attr(res,"condition")$message,
"\nDid you forget the dots in argument(s): ",
paste0(candidates, collapse = ", ")," ?")
}
res
})
fiendly_fun
}
Работает нормально, когда нет ошибок:
with_friendly_dot_error(addxy)(.x=1,.y=2)
# [1] 3
При необходимости выдает полезную ошибку:
with_friendly_dot_error(addxy)(.x=1, y=2)
# Error in with_friendly_dot_error(addxy)(.x = 1, y = 2) :
# argument ".y" is missing, with no default
# Did you forget the dots in argument(s): .y ?