Tidyeval with quoted function

tidyeval
rlang

#1

Hi, I'm new to tidyeval and wanted to do the following:

# This is working as expected
eval_tidy(quo("a" %>% paste("b")))
# "a b"

I expected the following snipped to return the same result as above but gettingsomething else. What am I missing here? How could I get the above result when having var_1 and var_2 as quo's?

var_1 <- quo("a")
var_2 <- quo(paste("b"))
eval_tidy(quo(!!var_1 %>% !!var_2))
# . ~ paste("b")
# <environment: 0x0000000015d8a798>

edit: It seems as if replacing "quo" with "expr" does the trick. Why is this not working with quo?


#2

Your var_2 is a quosure of the expression paste("b"), so I'm a little unclear on what your expected output is.

library(tidyverse)
library(rlang)

var_1 <- quo("a")
var_1
#> <quosure>
#>   expr: ^"a"
#>   env:  empty
var_2 <- quo(paste("b"))
var_2
#> <quosure>
#>   expr: ^paste("b")
#>   env:  global
eval_tidy(quo(!!var_1 %>% !!var_2))
#> . ~ paste("b")
#> <environment: 0x7f99840aee70>
eval_tidy(expr(!!var_1 %>% !!var_2))
#> . ~ paste("b")
#> <environment: 0x7fd33db6caf8>

Created on 2018-08-08 by the reprex package (v0.2.0.9000).


#3

When you replace quo by expr for the two vars, it is working as expected
I still try to understand the difference between both to be able to explain it clearly by words. I think I understand it conceptually but not enough to explain clearly. Great example then ! :wink:

library(rlang)
library(magrittr, warn.conflicts = FALSE) # for %>%
var_1 <- expr("a")
var_2 <- expr(paste("b"))
eval_tidy(quo(!!var_1 %>% !!var_2))
#> [1] "a b"

Created on 2018-08-08 by the reprex package (v0.2.0).


#4

my expected outcome is "a b".

I know that it's wokring with expr

var_1 <- expr("a")
var_2 <- expr(paste("b"))
eval_tidy(expr(!!var_1 %>% !!var_2))

but I do not understand why this is not working with quosures:

var_1 <- quo("a")
var_2 <- quo(paste("b"))
eval_tidy(quo(!!var_1 %>% !!var_2))

My understanding was, that the advantage of quosures over extressions is, that they take into account the environment. I my use case this would be useful so I am looking for a solution using "quo".


#6

I'm not sure why it doesn't work either, but one thing that you can experiment with is qq_show:

library(rlang)

var_1 <- quo("a")
var_2 <- quo(paste("b"))

qq_show(quo(!!var_1 %>% !!var_2))
#> quo((^"a") %>% (^paste("b")))

var_1 <- expr("a")
var_2 <- expr(paste("b"))

qq_show(quo(!!var_1 %>% !!var_2))
#> quo("a" %>% paste("b"))

Created on 2018-08-21 by the reprex package (v0.2.0).

As you can see, two ways of doing things are not exactly the same.


#7

This is a limitation due to the way magrittr uses NSE to do its magic: the RHS of %>% cannot be a quosure. This could be fixed in the next version.


#8

I had this feeling that it is due to magrittr, but couldn't think of a plausible explanation. Thanks for clearing this up!


#9

The wrapr dot pipe is a bit more circumspect and thus more compatible with other R non-standard systems than magrittr pipe is. For example it can already work your example (a difference being wrapr pipe requires explicit dots).

library("rlang")
library("magrittr")
library("wrapr")

var_1 <- expr("a")
var_2 <- expr(paste("b"))
eval_tidy(quo(!!var_1 %>% !!var_2)) # works get "a b"


var_1 <- quo("a")
var_2 <- quo(paste("b"))
eval_tidy(expr(!!var_1 %>% !!var_2)) # fails got a magrittr closure back

var_1 <- quo("a")
var_2 <- quo(paste(., "b"))
eval_tidy(expr(!!var_1 %.>% !!var_2)) # works get "a b"

We have a formal article on the pipe here.

The Bizzaro pipe also works.

eval_tidy(expr({!!var_1 ->.; !!var_2})) # works get "a b"