Open wch opened 3 years ago
Remove all these symbols from e1
and then e
will be GC-d:
❯ ls(environment(e1), all.names = TRUE)
[1] "..." ".Class" ".Generic" ".GenericCallEnv"
[5] ".GenericDefEnv" ".Group" ".Method"
Actually, scratch that, it won't....
Interesting -- if I add this to the inside of f.default
, then e
does get GC'd.
rm(., envir = .GenericCallEnv)
Or you can run this outside of the function, after e1
has been created:
rm(., envir = environment(e1)$.GenericCallEnv)
But when I poke at it, I don't see how .
holds a reference to e
.
Run this after the code above (except for the rm(list=ls()); gc()
at the end).
rls(environment(e1)$.GenericCallEnv$., all.names = TRUE)
#> [[1]]
#> character(0)
#>
#> [[2]]
#> [1] ".Random.seed" "e1" "f" "f.default" "finalized"
rm(., envir = environment(e1)$.GenericCallEnv)
gc()
#> finalized
expect_true(finalized)
But when I poke at it, I don't see how . holds a reference to e.
.
is the piped data in the pipe, so I guess .
is e
in this case.
I concur with @gaborcsardi:
> identical(environment(list(e1)[[1]])[[".GenericCallEnv"]][["."]], e)
[1] TRUE
Oh, duh, that makes sense. I just didn't have any identifying information in e
that made it easy to see that .
and e
were the same object.
I think this is a duplicate of #146. It's the conjunction of two factors:
We evaluate in a mask so we can refer to the placeholder multiple times, e.g. x %>% list(., .)
.
The .
binding is persistent to allow lazy evaluation (see "persistence of piped values" in https://magrittr.tidyverse.org/articles/tradeoffs.html).
This issue will disappear if you use the base pipe in the next version of R because it simply transforms the parse tree to the nested form. If you add this to your reprex, to use the same transformation, the issue goes away:
# Needs dev version
`%>%` <- magrittr::pipe_nested
I think I'd rather avoid making ad hoc cleanups for the specific case of S3 dispatch within the pipe mask because it might cause unintended effects and we're about to release magrittr.
Yes, it's the same as #146. I have a workaround in place for one of my packages, which cleans up this reference, because this issue was causing OOM to my users.
The pipe can prevent GC of an object that's passed into it. It happens when:
It seems that using the pipe causes there to be a reference to the object being piped
Here's an example where the use of
%>%
results in the object not being GC'd. However, if the function is called without the pipe, the object does get GC'd.