rtidyversemagrittr

retrieve .RData file of nameless object created with `magrittr::%>%`


I made a mistake and wrote this:

library(tidyverse)
list(x = rnorm(10)) %>% save(file = "test.RData")

instead of this:

x <- list(x = rnorm(10)) 
save(x, file = "test.RData")

As a result I cannot read "test.RData" back

load("test.RData")
ls()
character(0)

Yet the ".RData" file seems to contain something as the following command creates a 73 MB file compared with a 77 B with just ten values. It is just impossible to read back.

list(x = rnorm(10000000)) %>% save(file = "test.RData")

Interestingly the base r pipe |> throws an error

list(x = rnorm(10)) |> save(file = "test.RData")
Error in save(list(x = rnorm(10)), file = "test.RData") : 
  object ‘list(x = rnorm(10))’ not found

The mistake is easy to fix and I won't do it again but I am wondering what is happening under the hood:

  1. Why is save() not throwing an error when passed a nameless object with %>%?
  2. Would there be a way to load a .RData file written this way?

Solution

  • In fact it is loaded as the name . (dot) which was created by the %>% pipe. It is equivalent to the following which explicitly shows the name:

    rnorm(10) %>% save(., file = "test.RData")
    

    On the other hand the base pipe |> does not create a new name which accounts for the error if it is used. It works via substitution of the left hand side into the right hand side without creating a new name so is equivalent to the following which is an error:

    save(rnorm(10), file = "test.RData") }
    

    Note that

    rnorm(10) |> save(file = "test.RData") |> quote()
    ## save(rnorm(10), file = "test.RData")
    

    The reason the name does not appear is that ls does not show names that begin with dot unless called as

    ls(all = TRUE)
    

    Also note that load returns a character vector of names in it so that another way to get the name is to look at Names where

    Names <- load("test.RData")
    Names
    ## [1] "."