tidyr
tidyr copied to clipboard
`expand_grid()` evaluation environment
library(tidyr)
data <- tibble(foo=1)
foo <- bar <- 1:2
expand_grid(data, new = bar)
#> # A tibble: 2 × 2
#> foo new
#> <dbl> <int>
#> 1 1 1
#> 2 1 2
expand_grid(data, new = foo)
#> # A tibble: 1 × 2
#> foo new
#> <dbl> <dbl>
#> 1 1 1
This puzzled me then hit me that it behaves like a mutating function and this works :
expand_grid(data, new = .env$foo)
#> # A tibble: 2 × 2
#> foo new
#> <dbl> <int>
#> 1 1 1
#> 2 1 2
expand_grid(data, new = !!foo)
#> # A tibble: 2 × 2
#> foo new
#> <dbl> <int>
#> 1 1 1
#> 2 1 2
I'm not sure if the current behaviour is intended but it's undocumented. As far as I'm concerned I wouldn't mind have the dots evaluated outside of the data.
expand_grid() takes ..., the signature isn't .data, ... like mutate(). Just want to clarify that up front.
Beyond that, this is just the fact that expand_grid() evaluates its arguments sequentially like tibble() and mutate() (for better or worse), which makes your example a special case of this behavior
# second `foo` references first `foo` result
tidyr::expand_grid(foo = 1, new = foo)
#> # A tibble: 1 × 2
#> foo new
#> <dbl> <dbl>
#> 1 1 1
expand_grid() seems overly complicated for it's purpose. Maybe we can simplify it.
In my brain it should just capture ... with list2(), so yea, agreed
Like, when do you really use the "sequential evaluation" feature with expand_grid()? I don't think I ever have
I assume at the time we wanted to make it like tibble(), but I don't see why that matters. As long as it doesn't break a bunch of packages on CRAN, I think we can simplify.