title: Reading/Writing files using active bindings in R
body: <p>I am trying to implement in R SAS style libraries where you can define a library object which corresponds to a directory, then files to this disk by making assignments to the libraries members.</p>
  
  <p>The code below works for files that already exist.  So if you've got a directory with files already in it, you can read them by <code>myLib$file</code> and write to them using <code>myLib$file &lt;- value</code>.  What I can't figure out do is write a new file by doing <code>myLib$newfilename &lt;- value</code>.</p>
  
  <p>Anyone know how to implement this?</p>
  
  <pre><code>library(plyr)
  # What this does:
  # A function which creates an active binding to a given name, and using
  # the given directory path.  Upon access, the binding creates an environment
  # with active bindings for each file in that directory which will use readRDS
  # on access and saveRDS on change.
  
  # What this doesn't do:
  # Can't use this to write to a file that doesn't yet exist.  If the directory
  # has blah1.rdata and blah2.rdata, you can do myLib$blah3.rdata &lt;- 1.  Instead
  # of writing to disk, this will simply assign the value of 1 into an the env
  # returned by the outer active binding.
  
  # What tried and failed to do:
  # I tried to set this up so that the outer active binding catches where the
  # user tries 
  lib &lt;- function(libname,path){
    # Assign the name libname as an active binding in the global environment
    makeActiveBinding(
      libname,
      function(value){
        if(missing(value)){
          # If user is reading from binding, find all the files in the given
          # path that use the .rdata extension, create an environment, and
          # populate it with active bindings for each .rdata file which will
          # read/write using readRDS/saveRDS.
          regex &lt;- "^.*\\.(rdata)$"
          files &lt;- list.files(
            path=path,
            pattern = regex,
            ignore.case=TRUE
          )
          myEnv &lt;- new.env()
          myEnv$path &lt;- path
          l_ply(
            seq_along(files),
            function(i){
            makeActiveBinding(
              files[i],
              function(value){
                if(missing(value)){
                  readRDS(paste0(path,"/",files[i]))
                }else{
                  saveRDS(value,paste0(path,"/",files[i]))
                }
              },
              myEnv
            )
          })
          return(myEnv)
        }else{
          # If the user is writing to a binding, this should be set to
          # figure out what name the user is writing to, then do saveRDS
          # to the given library's path using that name as a filename.
          # 
          # Can't figure out how to make it work as I can't capture the
          # name being assigned to from the call...
          #
          # Note that this code only triggers and is necessary in the
          # case where the user is writing to a name that does not
          # correspond to an already existing file in the given directory
          #invisible(NULL)
        }
      },
      .GlobalEnv
    )
  }
  
  # Directory to use
  myDirectory &lt;- "./"
  
  # Pre-populate a couple files
  saveRDS(mtcars,paste0(myDirectory,"/","myCars.rdata"))
  saveRDS(iris,paste0(myDirectory,"/","myPlants.rdata"))
  
  # Initialize binding
  lib("myLib",path = myDirectory)
  
  # print object from disk
  print(head(myLib$myCars.rdata))
  
  # write over object using cars instead of mtcars
  myLib$myCars.rdata &lt;- cars
  
  # This works!  It prints cars now instead of mtcars even using readRDS
  print(head(readRDS(paste0(myDirectory,"/","myCars.rdata"))))
  print(head(myLib$myCars.rdata))
  
  # Wish I could write to a file that doesn't yet exist, but don't
  # know how to make it work
  myLib$somethingelse.rdata &lt;- 10
  </code></pre>