Closed iago-pssjd closed 4 years ago
This is a consequence of lazy evaluation because pivot_longer_spec()
checks its other inputs before forcing the main argument. Because of lazy evaluation the following pattern is unreliable in R because there's no guarantee that foo()
will first evaluate the first argument:
foo(x <- 1, x)
Note that the pattern you're using will also not work with the proposed base R pipe which will also be lazy.
What is your motivation for using this pattern? Is it just to spare an intermediate value? My feeling is that the pipe should not be overdone, using <-
here and there with good names really helps making code readable. Using <<-
inside {
inside %>%
is probably not good practice.
Thanks for the answer, @lionel- .
On my motivation, sometimes I have to execute really large quantities of code multiple times. To be faster (avoiding to run multiple instructions/assignments separately or having to select them previous to run) I see 3 options: either prepare alll the code in a script and execute the script, or separate the instructions by ;
or, as far as possible, collecting most consecutive instructions in a pipe workflow. Maybe the "good practice" is the first option, but the pipes workflow is more comfortable, at least for me, and allows to change the code on the fly easily.
Actually, I think I have just found a solution, since the code
data %T>%
{nspec <<- build_longer_spec(.,
cols = contains("spin"),
names_to = "pitch_type",
values_to = "avg_spin") %>%
mutate(pitch_type = sub("_spin", "", pitch_type))} %>%
{pivot_longer_spec(., spec = nspec, values_drop_na = TRUE)}
seems to work with the dev version. (even though, by your answer, I'm not sure to understand why it works?)
Please, let me know any other options you know to proceed in this way in this context of lazy evaluation. Otherwise, feel free to close.
Thank you for the details. I would be surprised if extra assignments are a bottleneck though. They might prevent the intermediary value from being collected for a little longer, but unless you're working with extremely large values that shouldn't be an issue.
seems to work with the dev version. (even though, by your answer, I'm not sure to understand why it works?)
I think it works because it expands to this: { .; pivot_longer_spec(.) }
. Curly blocks are not treated specially in magrittr, so the piped value is added to the block as first argument. It usually doesn't do anything, but in this case it forces evaluation of the input. Nice finding!
I think it works because it expands to this: { .; pivot_longer_spec(.) }. Curly blocks are not treated specially in magrittr, so the piped value is added to the block as first argument. It usually doesn't do anything, but in this case it forces evaluation of the input. Nice finding!
ah I see that @egnha and @hadley just discussed this in #224.
Thank you! I will go on testing dev magrittr
and I will adapt my code in this way when necessary. If I find any other issue I'll let you know.
After reading https://www.tidyverse.org/blog/2020/08/magrittr-2-0/ I decided to test new
magrittr
version. I installed it yesterday from github. I found now what seems to be a regression.Next code (original from SO) works on
magrittr 1.5
(I tried it even on https://rstudio.cloud)But it does not work with the current development version:
I use often this kind of code, and I think it is very useful since it allows to modify suitably the
pivot_wider
/pivot_longer
specs or to create other auxiliar variables (in place ofnspec
) without breaking the pipes workflow.Thank you!