2

Context

I am using in R, the "elipsis" or "dots" that wrap function calls

main_function <- function(...)

If I want to evaluate once, I do

main_function <- function(...) {
    res = list(...)}

It works fine

Problem

fun_A <- function(arg_A){
    print(paste("I am A", paste0(round(runif(arg_A, 0,1), 2),collapse = ", ")))
}

fun_B <- function(arg_B){
    print(paste("I am B", paste0(round(runif(arg_B, 1,2), 2),collapse = ", ")))
}

Here the result is evaluated once and replicate 3 times :

main_fun_wrong <- function(..., times) {
    res = list(...)
    replicate(times, eval(res))
}

main_fun_wrong(fun_A(1), fun_B(2), times = 3)

Here it works :

main_fun <- function(..., times) {
    calls = match.call(expand.dots = FALSE)$`...`
    replicate(times, lapply(1:length(calls), function(num) eval(calls[[num]])), simplify = F)
}

main_fun(fun_A(1),fun_B(2), times = 3)

But now if arg_A is an object rather than a value, it will fail finding the arg_A and arg_B in the environment.

main_fun_problem <- function(arg_A, arg_B) {
    main_fun(fun_A(arg_A),fun_B(arg_B), times = 3)
}

main_fun_problem(1,2)

I got an error :

Error in fun_A(arg_A) : object 'arg_A' not found

I do not know what R do when it find list(...) the first time in first example but I just want to repeat it multiple times.

Community
  • 1
  • 1
zakrapovic
  • 413
  • 3
  • 17

1 Answers1

0

Here is my solution, any alternative will be enjoyed.

The things is to substitute the variable by it's value at the moment we call the function.

main_fun_solution <- function(arg_A, arg_B) {
    eval(substitute(main_fun(fun_A(arg_A),fun_B(arg_B), times = 3), list("arg_A" =  arg_A, "arg_B" =  arg_B)))
}

main_fun_solution(1,2)

NB: list("arg_A" = arg_A, "arg_B" = arg_B)` makes my heart bleed (the overall solution actually)

zakrapovic
  • 413
  • 3
  • 17
  • Just came across [this](http://stackoverflow.com/questions/29084193/how-to-not-fall-into-rs-lazy-evaluation-trap?rq=1). I will read further, it looks like a good alternative. – zakrapovic Apr 28 '16 at 16:52