Using pipe syntax to save .RData file seems not to work as expected

magrittr

#1

I just spent several hours trying to figure out why my package won't build.

==> devtools::document(roclets=c('rd', 'collate', 'namespace', 'vignette'))

Updating xxxx documentation
Loading xxxx 
Error: 'yyyy' is not an exported object from 'namespace:xxxx'
Execution halted

Exited with status 1.

I spent a long time searching around build options and namespaces, but the source of the problem is in the way I was saving an .RData file. I had been using a pipeline syntax which seems not to work as I was expecting. reprex below:

library(magrittr)

# Why are these not equivalent?
save(iris, file = "eg1.RData")
iris %>% save(file = "eg2.RData")

# This works
load("eg1.RData")
rm(iris)

# This doesn't
load("eg2.RData")
rm(iris)
#> Warning in rm(iris): object 'iris' not found

The problem is solved (don't use obj %>% save()) and I can build the package, but I like using pipes and I'm curious as to why this doesn't work.


#2

It is a case of too many functions hoping they are the only one re-writing code (each one is consuming some of the referential transparency that is the property of normal value-oriented code, and once you are out things are not good). save()'s first argument is ... and it uses values in those positions to both get data and names of data. magrittr essentially re-writes the call as something like . <- iris; save(., file = "eg2.RData"). So the save function things the name of the value is often "." or "value".

You can confirm this with the following code.

library("magrittr")
iris %>% save(file = "eg2.RData")
. <- NULL
load("eg2.RData")
summary(.)

Also saveRDS() is unlikely to have the same problem, as it does not need the name of the object.


#3

Thanks for the explanation about "." and ... as a first argument.

As far as I can see, files written by saveRDS() aren't loaded correctly as package data, or am I using it incorrectly?


#4

Files saved with saveRDS() need to be read by readRDS(). What is happening with save() is how it gets the names of what to save. Would work/fail the same way with non-package data.