0

I have a “master” function foo from which I need to call two other functions fun1 and fun2. Each of these has separate argument sets which I'd like to set from outside.

library(tidyverse)
#> Registered S3 methods overwritten by 'ggplot2':
#>   method         from 
#>   [.quosures     rlang
#>   c.quosures     rlang
#>   print.quosures rlang

fun1 <- function(a, c) {
  print(glue::glue("a is {a}"))
  print(glue::glue("c is {c}"))
}

fun2 <- function(e, g) {
  print(glue::glue("e is {e}"))
  print(glue::glue("g is {g}"))
}

foo <- function(something, additional_args) {
  print(glue::glue("Called with {something}"))
  # I know I can do this, but I don't want to explicitly specify a, c, e and g here!)
  fun1(additional_args$fun1_args$a, additional_args$fun1_args$c)
  fun2(additional_args$fun2_args$e, additional_args$fun2_args$g)
}

foo("something", additional_args = list(
  fun1_args = list(a = "b", c = "d"),
  fun2_args = list(e = "f", g = "h")
))
#> Called with something
#> a is b
#> b is d
#> c is f
#> d is h

Created on 2019-07-17 by the reprex package (v0.3.0)

Obviously, it's not very nice that I have to repeat the names of the arguments inside foo. And the functions fun1 and fun2 may take many more arguments, or not all of them, or have some defaults.

I don't think I've fully grasped quasiquotation. And I read through the documentation, but nothing there applies. I am not using ... anywhere since I don't want to mix up arguments for function fun1 and fun2.

How can I replace these weird calls, in which I explicitly specify the arguments, so that they just forward the arguments instead?

  fun1(additional_args$fun1_args$a, additional_args$fun1_args$c)
  fun2(additional_args$fun2_args$e, additional_args$fun2_args$g)

I have tried

  fun1_args = enquos(additional_args$fun1_args)
  fun1(!!! fun1_args)

But it says:

Error: Inputs to capture must be argument names

I've also tried fun1(!!!additional_args$fun1_args), but it says:

Error in !additional_args$fun1_args : invalid argument type

slhck
  • 36,575
  • 28
  • 148
  • 201
  • `do.call(fun1, additional_args$fun1_args)`. Also note that you define the additional_args incorrectly, providing arguments 'a' and 'c' for function `fun1`, while `fun1` is supposed to take 'a' and 'b'. – January Jul 17 '19 at 12:39
  • That works, thanks. If I want to add another parameter, I have to run `do.call(fun1, append(additional_args$fun1_args, list(another_parameter = "test")))` … would you like to provide a full answer? – slhck Jul 17 '19 at 12:48
  • And thanks for the info, I fixed the code. Quite apparently, it never executed that far. – slhck Jul 17 '19 at 12:48
  • No need for a full answer. `append` works, but so does `c(additional_args$fun1_args, another_parameter="test")`, which is shorter. – January Jul 17 '19 at 12:57
  • Well, if there were an answer, the question could be marked as solved. If you don't want to provide one, I can write one up though. – slhck Jul 17 '19 at 13:16
  • No you can't, someone marked it as a duplicate ;-) – January Jul 17 '19 at 13:17
  • Eh, of course. Good duplicate question – wasn't able to find that when I was searching. – slhck Jul 17 '19 at 13:21

0 Answers0