eladin
eladin

Reputation: 121

enquo() inside a magrittr pipeline

I just would like to understand what's going wrong here. In the first case (working), I assign the enquo()-ted argument to a variable, in the second case, I use the enquoted argument directly in my call to mutate.

library("dplyr")
df <- tibble(x = 1:5, y= 1:5, z = 1:5)

# works
myfun <- function(df, transformation) {
  my_transformation <- rlang::enquo(transformation)
  df %>% 
    gather("key","value", x,y,z) %>% 
    mutate(value = UQ(my_transformation))
}
myfun(df,exp(value))

# does not work
myfun_2 <- function(df, transformation) {
  df %>% 
    gather("key","value", x,y,z) %>% 
    mutate(value = UQ(rlang::enquo(transformation)))
}
myfun_2(df,exp(value))
#>Error in mutate_impl(.data, dots) : Column `value` is of unsupported type closure

Edit Here are some more lines to think about :)

Wrapping the call into quo() it looks as if the expression to evaluate is "built" correctly

# looks as if the whole thing should be working
myfun_2_1 <- function(df, transformation) {
  quo(df %>% 
    gather("key","value", x,y,z) %>% 
    mutate(value = UQ(rlang::enquo(transformation))))
}
myfun_2_1(df,exp(value))

If you tell this to eval_tidy, it works (it doesn't work without quo())

# works
myfun_2_2 <- function(df, transformation) {
  eval_tidy(quo(df %>% 
    gather("key","value", x,y,z) %>% 
    mutate(value = UQ(rlang::enquo(transformation)))))
}
myfun_2_2(df,exp(value))

If you don't use the pipe, it also works

# works
myfun_2_3 <- function(df, transformation) {
  mutate(gather(df,"key","value", x,y,z), value = UQ(rlang::enquo(transformation)))
}
myfun_2_3(df,exp(value))

Regarding the error message, this is what one gets, when one tries to pass types that are not supported by data.frames, eg.

mutate(df, value = function(x) x) # Error in mutate_impl(.data, dots) : Column value is of unsupported type closure

To me it looks as if the quosure in myfun_2 isn't evaluated by mutate, which is somehow interesting/non-intuitive behaviour. Do you think I should report this to the developers?

Upvotes: 3

Views: 375

Answers (1)

Lionel Henry
Lionel Henry

Reputation: 6801

This limitation is solved in rlang 0.2.0.

Technically: The core of the issue was that magrittr evaluates its arguments in a child of the current environment. This is this environment that contains the . pronoun. As of 0.2.0, capture of arguments with enquo() and variants is now lexically scoped, which means it looks up the stack of parent environments to find the argument to capture. This solves the magrittr problem.

Upvotes: 6

Related Questions