Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing map() .x to a function

Tags:

r

purrr

reactable

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?

like image 608
Gakku Avatar asked Sep 15 '25 06:09

Gakku


1 Answers

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.

like image 179
caldwellst Avatar answered Sep 16 '25 18:09

caldwellst