r-lib / rlang

Low-level API for programming with R
https://rlang.r-lib.org
Other
501 stars 137 forks source link

Unquoting language objects with `!!!` warning alternative #1233

Closed laresbernardo closed 3 years ago

laresbernardo commented 3 years ago

Hi! This is more of a question rather than an issue with rlang. I started getting these warnings (once per session) some time ago for some old functions that actually don't break the code but are annoying (I guess that's the idea):

Warning message:
Unquoting language objects with `!!!` is deprecated as of rlang 0.4.0.
Please use `!!` instead.

  # Bad:
  dplyr::select(data, !!!enquo(x))

  # Good:
  dplyr::select(data, !!enquo(x))    # Unquote single quosure
  dplyr::select(data, !!!enquos(x))  # Splice list of quosures

What happens is that depending on how many inputs are passed to ..., the function plots A or B (here's the actual function: distr). To do so, the code manually picks the first one or the second one with !!!enquos(...)[[n]]. Here is a reproducible example:

options(lifecycle_repeat_warnings = TRUE) # So we can check if any alternative solution works
library(dplyr)
data("starwars")
foo <- function(x, ...) {
  temp <- enquos(...)
  group_by(x, !!!temp[[1]]) %>% tally()
}
foo(starwars, sex, gender) # Will ignore gender in this case

What would be the correct way of doing this? Thanks!

markfairbanks commented 3 years ago

One easy way to fix your issue is to use single brackets like this !!!enquos(...)[n].

!!! splices lists. If you use [[n]] it returns a single quosure because it extracts the individual element of the list. However if you use [n] it returns a list (of length 1), with the single element being your target quosure.

So now this works without warnings:

options(lifecycle_repeat_warnings = TRUE) # So we can check if any alternative solution works
library(dplyr)
data("starwars")
foo <- function(x, ...) {
  temp <- enquos(...)
  group_by(x, !!!temp[1]) %>% tally()
}

foo(starwars, sex, gender) # Will ignore gender in this case
#> # A tibble: 5 x 2
#>   sex                n
#>   <chr>          <int>
#> 1 female            16
#> 2 hermaphroditic     1
#> 3 male              60
#> 4 none               6
#> 5 <NA>               4
laresbernardo commented 3 years ago

That's exactly it @markfairbanks Thanks a lot! can't believe it was this easy! 😂 Actually found another way of doing so that also worked for me.