Stumbled upon this question while searching for something related. While I realize that this is several years old, the responses appear unsatisfactory, and there does not appear to be any off-the-shelf solution to the question.
It is possible to make an (inelegant) workaround, using a combination of the formals and environment functions. The example below extracts arguments from the environment using names extracted from formals, then appends the ellipsis-list. If you wish to have the values as they were set at the time of function call, set the orig_values argument to TRUE. The function only includes variables implicitly or explicitly set at function call.
allargs <- function(orig_values = FALSE) {
# get formals for parent function
parent_formals <- formals(sys.function(sys.parent(n = 1)))
# Get names of implied arguments
fnames <- names(parent_formals)
# Remove '...' from list of parameter names if it exists
fnames <- fnames[-which(fnames == '...')]
# Get currently set values for named variables in the parent frame
args <- evalq(as.list(environment()), envir = parent.frame())
# Get the list of variables defined in '...'
args <- c(args[fnames], evalq(list(...), envir = parent.frame()))
if(orig_values) {
# get default values
defargs <- as.list(parent_formals)
defargs <- defargs[unlist(lapply(defargs, FUN = function(x) class(x) != "name"))]
args[names(defargs)] <- defargs
setargs <- evalq(as.list(match.call())[-1], envir = parent.frame())
args[names(setargs)] <- setargs
}
return(args)
}
tempf <- function(a, b = 2, ...) {
d <- 5
b <- 3
cat("Currently set values defined in call or formals\n")
print(allargs())
cat("Values as defined at the time of the call\n")
print(allargs(T))
}
tempf(1, c = 3)
Currently set values defined in call or formals
$a
[1] 1
$b
[1] 3
$c
[1] 3
Values as defined at the time of the call
$a
[1] 1
$b
[1] 2
$c
[1] 3
The function by @Intelligentaccident was almost exactly what I was after. The only problem I had was some functions I needed it for had ...'s and others didn't. I have made his code even more inelegant (actually, I thought it was pretty clear and well commented) in order to work with both types of function. Thanks so much @Intelligentaccident your code has made my life much easier.
allargs <- function(orig_values = FALSE) {
# get formals for parent function
parent_formals <- formals(sys.function(sys.parent(n = 1)))
# Get names of implied arguments
fnames <- names(parent_formals)
# Remove '...' from list of parameter names if it exists
fnames <- fnames[which(fnames != '...')]
# Get currently set values for named variables in the parent frame
args <- evalq(as.list(environment()), envir = parent.frame())[fnames]
# Get the list of variables defined in '...'
if (any(names(parent_formals) == '...')) args <- c(args,evalq(list(...), envir = parent.frame()))
if(orig_values) {
# get default values
defargs <- as.list(parent_formals)
defargs <- defargs[unlist(lapply(defargs, FUN = function(x) class(x) != "name"))]
args[names(defargs)] <- defargs
setargs <- evalq(as.list(match.call())[-1], envir = parent.frame())
args[names(setargs)] <- setargs
}
return(args)
}