When you convert a string to a symbol, it prints without the quotes, but that's NOT what unquoting means (we'll get back to that in the end).
rlang::sym()
is creating a symbol from a string, it's almost the same as base::as.symbol()
(tiny differences irrelevant to this answer), itself an alias for base::as.name()
:
nm <- "Sepal.Width"
x <- rlang::sym(nm)
x
#> Sepal.Width
typeof(x)
#> [1] "symbol"
identical(x, as.symbol(nm))
#> [1] TRUE
Those don't work, as x
and nm
are respectively a symbol and a character, so I can't multiply them by 2
:
dplyr::mutate(head(iris),SW2 = nm * 2)
#> Error in nm * 2: argument non numérique pour un opérateur binaire
dplyr::mutate(head(iris),SW2 = x * 2)
#> Error in x * 2: argument non numérique pour un opérateur binaire
!!
doesn't do anything by itself and is not a real operator, it tells mutate()
to do something though, because mutate()
is designed to recognize it.
What it tells to mutate()
is to act as if !!x
was replaced by the quoted content of x.
# equivalent to dplyr::mutate(head(iris), Sepal.Width * 2)
dplyr::mutate(head(iris), !!x * 2)
#> Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#> 1 5.1 3.5 1.4 0.2 setosa
#> 2 4.9 3.0 1.4 0.2 setosa
#> 3 4.7 3.2 1.3 0.2 setosa
#> 4 4.6 3.1 1.5 0.2 setosa
#> 5 5.0 3.6 1.4 0.2 setosa
#> 6 5.4 3.9 1.7 0.4 setosa
#> Sepal.Width * 2
#> 1 7.0
#> 2 6.0
#> 3 6.4
#> 4 6.2
#> 5 7.2
#> 6 7.8
dplyr::mutate(head(iris), !!sym("Sepal.Width") * 2)
would give the same output.
Why it is called unquoting might be easier to understand by looking at this other equivalent call :
quoted <- quote(Sepal.Width * 2)
dplyr::mutate(head(iris), !!quoted)
See help("!!")
for more details.