Using get inside lapply, inside a function

别说谁变了你拦得住时间么 提交于 2019-11-29 03:46:40

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')

Just convert the current environment into a list:

foo <- function(a=1, b=5, h='coconut') {
  as.list(environment())
}
foo(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)
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!