this may seem like a overly complicated question, but it has me driving me a little nuts for some time. It is also for curiosity, because I already have a way of doing what
Edit of 2013-08-05
Using sapply()
instead of lapply()
, simplifies this considerably:
foo4 <- function(a=1, b=5, h='coconut') {
frm <- formals(sys.function())
sapply(names(frm), get, envir=sys.frame(sys.parent(0)), simplify=FALSE)
}
foo4(b=0, h='mango')
This, though, without sapply()
or lapply()
might be the more elegant solution:
foo5 <- function(a=1, b=5, h='coconut') {
modifyList(formals(sys.function()), as.list(match.call())[-1])
}
foo5(b=0, h='mango')
Original post (2011-11-04)
After casting about a bit, this looks to be the best solution.
foo <- function(a=1, b=5, h='coconut') {
frm <- formals(foo)
parms <- lapply(names(frm), get, envir=sys.frame(sys.parent(0)))
names(parms) <- names(frm)
return(parms)
}
foo(b=0, h='mango')
# $a
# [1] 1
# $b
# [1] 0
# $h
# [1] "mango"
There's some subtle stuff going on here with the way that lapply
scopes/evaluates the calls that it constructs. The details are hidden in a call to .Internal(lapply(X, FUN))
, but for a taste, compare these two calls:
# With function matched by match.fun, search in sys.parent(0)
foo2 <- function(a=1, h='coconut') {
lapply(names(formals()),
get, envir = sys.parent(0))
}
# With anonymous function, search in sys.parent(2)
foo3 <- function(a=1, h='coconut') {
lapply(names(formals()),
FUN = function(X) get(X, envir = sys.parent(2)))
}
foo4(a=0, h='mango')
foo5(a=0, h='mango')
This is adapted from @Josh O'Brien's solution above using sapply
to automatically assign the correct names to the resulting list (saves one line of code):
foo <- function(a=1, b=5, h='coconut') {
frm <- formals(foo)
parms <- sapply(names(frm), get, envir=sys.frame(sys.parent(-1)), simplify=FALSE)
return(parms)
}
Just convert the current environment into a list:
foo <- function(a=1, b=5, h='coconut') {
as.list(environment())
}
foo(a = 0, h = 'mango')