What you've shown has nothing to do with formulas, that's just R parsing a string. We don't recommend meta-programming with strings as it's not robust, and not powerful. It's not a tidyverse thing, experimented base R programmers are likely to give the same advice.
Here is an approach to reducing a list of names or expressions to a single expression. First we'll need to define some tools, hopefully they'll live in a package sometime in the future:
syms_reduce <- function(syms, op = "+") {
exprs_reduce(syms(syms), op = op)
}
exprs_reduce <- function(exprs, op = "+") {
n <- length(exprs)
if (length(exprs) == 0) {
abort("Empty list of expressions")
}
if (length(exprs) == 1) {
return(exprs[[1]])
}
op <- sym(op)
purrr::reduce(exprs, function(x, y) expr((!!op)(!!x, !!y)))
}
We have one function syms_reduce()
that takes symbols or strings as inputs, and the other exprs_reduce()
takes a list of arbitrary expressions. Let's try syms_reduce()
to create a sum, the default operation:
syms_reduce(c("a"))
#> a
syms_reduce(c("a", "b", "c"))
#> a + b + c
This function is robust to any weird names that might come up in messy data:
syms_reduce(c("1()", "`a`e", "_foo"))
#> `1()` + `\`a\`e` + `_foo`
You can specify a different operation:
syms_reduce(c("a", "b", "c"), op = "*")
#> a * b * c
And it even works with regular functions!
syms_reduce(c("a", "b", "c"), op = "plus")
#> plus(plus(a, b), c)
As for exprs_reduce()
, it accepts any expression as input, even other sums:
exprs <- exprs(foo(), bar(baz), quux + blip)
exprs_reduce(exprs, "-")
#> foo() - bar(baz) - (quux + blip)
Note how the operator precedence of the last input quux + blip
was handled gracefully.
String meta-programming simply doesn't have this kind of flexibility and robustness.