In rlang, in quo(!!<expression>), evaluation from !! is not occurring right away

library(rlang)

In rlang, I have this.

quo(list(code = 1:10, data = !!(1:10)))

expr: ^list(code = 1:10, data = <int: 1L, 2L, 3L, 4L, 5L, ...>)
env: global

Then, I get an answer like this.

eval_tidy(quo(list(code = 1:10, data = !!(1:10))))
$code
[1] 1 2 3 4 5 6 7 8 9 10

$data
[1] 1 2 3 4 5 6 7 8 9 10

According to the definition
The !! operator unquotes its argument. It gets evaluated immediately in the surrounding context.

But, if I evaluation is right away, then I have this.

!!(1:10)
[1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE

So, why is !!(1:10)

different from . . .

$data
[1] 1 2 3 4 5 6 7 8 9 10

Thanks,
Andre

I think I understand the source of the confusion here. rlang::!!() can only be used on a quasiquoted argument, so the !(1:10) and !!(1:10) are actually using the logical ! operator.

library(rlang)
!(1:10)
#>  [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
!!(1:10)
#>  [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
rlang::`!!`(1:10)
#> Error: `!!` can only be used within a quasiquoted argument
data = !!(1:10)
data
#>  [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
list(code = 1:10, data = !!(1:10))
#> $code
#>  [1]  1  2  3  4  5  6  7  8  9 10
#> 
#> $data
#>  [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
quo(list(code = 1:10, data = !!(1:10)))
#> <quosure>
#>   expr: ^list(code = 1:10, data = <int: 1L, 2L, 3L, 4L, 5L, ...>)
#>   env:  global

Created on 2018-10-04 by the reprex package (v0.2.1.9000)

1 Like

Unfortunately !! is not a real operator, and it only works as an unquote operator within quasiquoting functions. In normal R semantics, !! is double negation (which, effectively amounts to coercing a vector to logical). See "The polite fiction" section in the next edition of adv-r: https://adv-r.hadley.nz/quasiquotation.html#the-polite-fiction-of.

The thing being evaluated immediately is the operand of the fake operator !! — in this case (1:10) — not the whole expression.

4 Likes

Thanks Mara and Lionel.

The answers make sense.

A follow up question follows.

If quo quotes and captures the environment, what is the advantage of using !! within (inside) of quo().
Since the entire thing ( like quo() ) is quoted anyways (means FROZEN), why would someone want to do quo( !! ). Does !! inside of quo ( like quo( !! ) ) protect or 'do something' different than quo without the !! ( like quo( ) )?

Thanks,
Andre

1 Like

Let me follow up again.

  1. question
    Is quo( !! ), something needed for 'building expressions?

E.g.
Tidy evaluation in 5 mins

  1. question (harder)
    Is quo( !! ), somthing that represents some protection
    one may need in in passing information through
    the argument list of a function?

E.g.
fn <- function( x ) {
...
}
fn(!!y)

Unquoting within an expression allows you to have a varying part inside the otherwise frozen expression. See https://tidyeval.tidyverse.org/modifying-inputs.html#expanding-quoted-expressions-with-expr

6 Likes