Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

eval_tidy failures: induced by differences in dplyr::mutate and tidytable::dt_mutate #39

Closed
xiaodaigh opened this issue Mar 16, 2020 · 5 comments

Comments

@xiaodaigh
Copy link

I think there is a difference between how dplyr treats quoted code and how tidytable treats them.

This is a blocking issue for integrating tidytable with disk.frame, see DiskFrame/disk.frame#271

fn = function(a,b) {
  a + b
}

# dplyr seems to be able to handle this correctly
mwe_mutate = function(...) {
  quo_dotdotdot = rlang::enquos(...)
  data = data.frame(num = 1:100)
  code = rlang::quo(mutate(data, !!!quo_dotdotdot))  
  rlang::eval_tidy(code)
}

mwe_mutate(b = fn(num, num))

# tidytable seems to fail 
mwe_dt_mutate = function(...) {
  quo_dotdotdot = rlang::enquos(...)
  data = data.frame(num = 1:100)
  code = rlang::quo(dt_mutate(data, !!!quo_dotdotdot))  
  rlang::eval_tidy(code)
}

mwe_dt_mutate(b = fn(num, num)) # this gives an error
@xiaodaigh xiaodaigh changed the title eval_tidy failures: induced by differences in dplyr::mutate and tidytable::d_mutate eval_tidy failures: induced by differences in dplyr::mutate and tidytable::dt_mutate Mar 16, 2020
@markfairbanks
Copy link
Owner

markfairbanks commented Mar 16, 2020

This issue comes from the fact that quosures don't work inside of data.table.

For this reason you can't use rlang::enquos(), and must instead use rlang::enexprs():

mwe_dt_mutate = function(...) {
  expr_dotdotdot = rlang::enexprs(...) # Use enexprs() instead of enquos()
  data = data.frame(num = 1:100)
  code = rlang::quo(dt_mutate(data, !!!expr_dotdotdot))
  rlang::eval_tidy(code)
}

mwe_dt_mutate(b = fn(num, num))

@markfairbanks
Copy link
Owner

Here's a good example of a very basic mutate translation:

quo_dt_mutate <- function(.data, ...) {
  dots <- enquos(...)
  
  eval_tidy(expr(
    .data[, ':='(!!!dots)][]
  ))
}

expr_dt_mutate <- function(.data, ...) {
  dots <- enexprs(...)
  
  eval_tidy(expr(
    .data[, ':='(!!!dots)][]
  ))
}

test_df <- data.table(x = 1:3)

quo_dt_mutate(test_df, double_x = x * 2) # Fails

expr_dt_mutate(test_df, double_x = x * 2) # Works

@markfairbanks
Copy link
Owner

markfairbanks commented May 24, 2020

This issue is now fixed in the new version of tidytable up on CRAN (v0.5.0).

Note there's been a small syntax change where all functions now use verb.() syntax instead of dt_verb(). For example dt_mutate() has been renamed to mutate.().

The dt_ versions still exist in tidytable, but it seems like a lot of packages are using that prefix - so I decided to change things during version v0.4.0.

library(tidytable, warn.conflicts = FALSE)

fn = function(a,b) {
  a + b
}

mwe_dt_mutate = function(...) {
  quo_dotdotdot = rlang::enquos(...)
  data = data.frame(num = 1:100)
  code = rlang::quo(mutate.(data, !!!quo_dotdotdot))  
  rlang::eval_tidy(code)
}

mwe_dt_mutate(b = fn(num, num)) %>% head()
#>    num  b
#> 1:   1  2
#> 2:   2  4
#> 3:   3  6
#> 4:   4  8
#> 5:   5 10
#> 6:   6 12

@xiaodaigh
Copy link
Author

I will take a look. Busy with work and some Julia open source work atm.

@markfairbanks
Copy link
Owner

Sounds good, if there's anything I can help with let me know

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants