This might seem like a silly question, but for the life of me I cannot figure it out so appreciate any help.
I am trying to pass .x (from purrr::map) to a function so in the end I get a list of functions (I will use this eventually to pass a list of column definitions with functions inside to reactable). This is a very basic example of what I want to do:
a = list("b", "c")
t <- map(a, ~{
function(.x){
print(x)
}
})
The result I am looking for is:
> t
[[1]]
function(b){
print(x)
}
[[2]]
function(c){
print(x)
}
but I get:
> t
[[1]]
function(.x){
print(x)
}
[[2]]
function(.x){
print(x)
}
Is what I am looking for possible?
CodePudding user response:
You can get what you want by using a wrapper function to create a new function. Within the wrapper, create an empty function, set the args to the value x
passed in (so if x="a"
, with give the equivalent of alist(a=)
), and then also parse a string to the body. Then the returned list will be the functions you want.
library(purrr)
function_crafter <- function(x) {
f <- function() {}
args <- setNames(list(bquote()), x)
formals(f) <- args
body(f) <- parse(text = paste0("print(", x, ")"))
f
}
a <- list("b", "c")
fl <- map(a, function_crafter)
fl[[1]](b=2)
#> [1] 2
fl[[2]](c=39)
#> [1] 39
fl
#> [[1]]
#> function (b)
#> print(b)
#> <environment: 0x7fb68752aae0>
#>
#> [[2]]
#> function (c)
#> print(c)
#> <environment: 0x7fb687552818>
If you actually wanted the print()
in each function to simply be print(x)
rather than print(b)
or print(c)
, then that's even easier, just define the body of the function in its initialization.