4

Given function and test vector:

multiply_stuff <- function(...) {
    arguments <- list(...)
    Reduce(f = `*`, x = arguments)
}

test_vec <- c(1, 20, 3, 40, 5, 60)

I would like to create an unevaluated call automatically listing all arguments of the passed vector. In this example that would be equivalent of expression:

call("multiply_stuff",
     test_vec[1],
     test_vec[2],
     test_vec[3],
     test_vec[4],
     test_vec[5],
     test_vec[6])

Attempts

For instance for the vector:

test_vec_B <- c(1, 5, 6, 8, 9, 11, 12, 14, 20, 11)

I would like to automatically list all test_vec_B arguments within call("multiply_stuff",...). Naturally this won't work:

call("multiply_stuff", test_vec_B)
call("multiply_stuff", list(test_vec_B))

Desired results

Unevaluated expression equivalent to:

call(
    "multiply_stuff",
    test_vec_B[1],
    test_vec_B[2],
    test_vec_B[3],
    test_vec_B[4],
    test_vec_B[5],
    test_vec_B[6],
    test_vec_B[7],
    test_vec_B[8],
    test_vec_B[9],
    test_vec_B[10]
)
2
  • 1
    Possibly related but without conclusive answer: stackoverflow.com/questions/42398790/…
    – LAP
    Commented Jun 14, 2018 at 8:30
  • @LAP Thanks for the link. In effect do.call offers something similar as it can take a list for its args. This said I'm looking to create an unevaluated expression and do.call evaluates.
    – Konrad
    Commented Jun 14, 2018 at 8:50

1 Answer 1

2

You can create a call object and then add arguments to it:

multiply_stuff <- function(...) {
  arguments <- list(...)
  Reduce(f = `*`, x = arguments)
}
test_vec_B <- c(1, 5, 6, 8, 9, 11, 12, 14, 20, 11)

get_call <- function(f, arg_vector){
  my_call <- call(f)
  my_call[2:(length(arg_vector) + 1)] <- arg_vector
  return(my_call)
}

multiply_stuff(1, 5, 6, 8, 9, 11, 12, 14, 20, 11)
[1] 878169600

test_call <- get_call("multiply_stuff", test_vec_B)
eval(test_call)
[1] 878169600

Explanation: when you create a call object, you can access/modify the function and its arguments by index just like usual. Index 1 is the function call, indices from 2 onwards are arguments.Run to verify:

test_call2 <- call("sum", 1, 2)
test_call2[1]
test_call2[2]
test_call2[3]
eval(test_call2)

test_call2[3] <- 1234
eval(test_call2)
1
  • Thanks very much, that's neat solution. I reckon that my_call[2:(length(arg_vector) + 1)] is the key here.
    – Konrad
    Commented Jun 14, 2018 at 15:00

Not the answer you're looking for? Browse other questions tagged or ask your own question.