2

I would like to create a result-vector of a sub-group of functions.

This is a simplified example of what I mean:

# create example functions
set.seed(999)

create_fun <- function(start, len) {
  res <- function() {
    seq(from = start, length.out = len)
  }
  res
}

for (i in 1:4) {
  eval(parse(text = paste0("f", i, "<-create_fun(", sample(1:10, 1), ",",     sample(2:5, 1), ")")))
  # btw is it possible to use something like assign instead of eval-parse?
}

# static version of what I want
c(f1(), f3(), f4())
# 4 5 6 7 8 9 7 8

# dynamic version of what I want
x <- c(f1 = TRUE, f2 = FALSE, f3 = TRUE, f4 = TRUE) # I'd like to start with a vector of function-names to use
# .. but now what?

How to do this properly?

r.user.05apr
  • 5,356
  • 3
  • 22
  • 39

2 Answers2

2

Here is a solution in base R:

unlist(lapply(names(x[x]), function(f) get(f)()))

[1] 4 5 6 7 8 9 7 8

First select names of functions you want to call. For each of them, get(function_name)() allows to evaluate them.

Please have a look at : Why is using assign bad?

Clemsang
  • 5,053
  • 3
  • 23
  • 41
1

A more straightforward way is to encapsulate your functional logic into a reusable generic:

sequence_creator <- function(args) {
  seq(from = args$start, length.out = args$len)
}

args_creator <- function(i) {
  # possibly use i in your function
  list(
    start = sample(1:10, 1), 
    len = sample(2:5, 1)
    )
}

Then you don't have loose functions floating around, you have the logic to create them each time you need them. You can use this in base R or the tidyverse-style.

# base R
y <- lapply(1:4, args_creator)
x <- c(T, F, T, T)
unlist(lapply(y[x], sequence_creator))

# tidyverse
library(purrr)
map(1:4, args_creator) %>% 
  keep(c(T, F, T, T)) %>% 
  map(sequence_creator) %>% 
  unlist()
Brian
  • 7,900
  • 1
  • 27
  • 41