How can I implement glue() for quosures?

dplyr's single-table verbs have scoped variants.

library(dplyr, warn.conflicts = FALSE)

d <- data.frame(
  a = 1:4,
  b = 1:4,
  c = 1:4
)

d %>%
  # a spoiler: funs() will be deprecated :P
  mutate_at(vars(a, b), list(~ . * 2))
#>   a b c
#> 1 2 2 1
#> 2 4 4 2
#> 3 6 6 3
#> 4 8 8 4

This is very handy. But, sometimes I feel the same thing can be achieved without the scoped ones if we have something like glue_quo() that takes raw expression and list of lists of symbols, and return the list of quosures. For example, I want

glue_quo(!!x := !!x * 2, list(x = syms(c("a", "b"))))
# or glue_quo(!!x := !!x * 2, list(x = c(a, b)))

would return list(a = quo(a * 2), b = quo(b * 2)) so that we can unquote it inside mutate() by !!!. But, I don't know how to implement it... This is what I tried and failed (Sorry for the terrible code :roll_eyes: ):

col_syms <- syms(c("a", "b"))
col_envs <- lapply(col_syms, function(s) {
  rlang::new_environment(list(x = s))
})

# do not unquote
expr_tmpl <- quote(rlang::quo(!!x := !!x * 2))
quos <- lapply(col_envs, rlang::eval_tidy, expr = expr_tmpl)

quos
#> [[1]]
#> <quosure>
#> expr: ^a := a * 2
#> env:  000000001E4FA038
#> 
#> [[2]]
#> <quosure>
#> expr: ^b := b * 2
#> env:  000000001E50C620

d %>%
  mutate(!!!quos)
#> Error in mutate_impl(.data, dots): Evaluation error: could not find function ":=".

Does anyone have a good idea?

I don't have answer to your question, but can you expand on that instead?
P.S. I found a PR where this is being worked on - https://github.com/tidyverse/dplyr/pull/3930
Thanks, I had no idea :slight_smile:

It seems ongoing here: https://github.com/tidyverse/dplyr/pull/3930

1 Like

(To be clear, my question is nothing related to the deprecation, this is just out of my curiosity)

Maybe this?

flatten(map(syms(c('a', 'b')), ~ exprs(!!.x := (!!.x * 2))))
data.frame(a = 1, b = 1) %>%
  mutate(!!!flatten(map(syms(c('a', 'b')), ~ exprs(!!.x := (!!.x * 2)))))

gives

a b
2 2

3 Likes

Nice, this feels something I wanted :slight_smile: Using expression is a chioce. Thanks!