Open
Description
The pipe can prevent GC of an object that's passed into it. It happens when:
- The object is piped to a function
- The function is an S3 method
- The method returns a function (or something that captures the environment), and the result is saved
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.
library(magrittr)
library(testthat)
f <- function(x, ...) {
UseMethod("f")
}
f.default <- function(x, ...) {
# Don't hold onto a reference to x
rm(x)
function() {
123
}
}
e <- new.env()
finalized <- FALSE
reg.finalizer(e, function(e) { finalized <<- TRUE; message("finalized") })
e1 <- e %>% f()
# If this line is used instead of the one above, then `gc()` collects `e` and finalizer runs.
# e1 <- f(e)
rm(e); gc(); gc()
expect_true(finalized)
#> Error: `finalized` isn't true.
# Clean up
rm(list=ls()); gc()
#> finalized