Creative use of the Archive object

Hi! I recently discovered the existence of the Archive object. It belongs to a family of objects such as Library, etc. It has been available in the standard library for a very long time and I never really encountered it anywhere in the wild. I am a big fan of automatic permanent storage in what can otherwise be a temporary/ephemeral working session.

I can think of a million ways to use it, for instance as an alternative to loading a file containing basic data structures, as a pattern storage method, etc. Is there any known example of this object being used for creating or improvising music?

I’ve used an Archive local to my current project folder to store state things about a piece I’m working on, for example EQ settings and other similar things that I want to be sort-of-persistent.

Do you just automate loading from archive during boot and saving on quit? One thing that I’ll try is to integrate it more deeply with the pattern system in order to keep a memory of the last form of patterns played in a specific session (e.g _rehearsal project X). Interpolation between different projects/states is also interesting.

Archive is already/automatically read at startup, and written at shutdown (see Process:startup and Process:shutdown. I would caution against trusting the “write on shutdown” too much, since it obviously doesn’t do this if you crash or if there’s an error anywhere else in shutdown code. If I’m writing something that I really want to make sure is saved, I use something like this (with the Collapse quark):

ArchiveLazyWrite { 
   classvar <>func;
   *initClass { func = Collapse({ Archive.write }, 10) }
}

+Archive {
   *lazyWrite {
      ArchiveLazyWrite.func.();
   }
} 

And then call Archive.lazyWrite after I make archive changes (Collapse just avoids writing to disk again and again in case of repeated changes).

More specifically, for personal projects, I’ll often use a class based on Singleton, with my current project path as the name (so, I have one global object per project folder, just in case I end up running code from multiple project folders at a given time). You can use a MultiLevelIdentityDictionary for storage, and expose at and put methods that forward to this, and do the lazy read/write. A quick mockup (just off the top of my head, so this might not work):

LocalStorage : Singleton {
  classvar <>timeBetweenWrites=10;
  var storage, doWrite;

  init {
    |name|
    storage = MultiLevelIdentityDictionary();
    doWrite = Collapse({ this.write }, timeBetweenWrites);
    this.read();
  }
  
  read { /* same read code from Archive, using `name` as the path */ } 
  write { /* same write code from Archive, using `name` as the path */ } 

  at { |...path| ^storage.atPath(path) }

  put { 
    |...path| 
    storage.put(*path);
    doWrite.();
  }
}

Then, you can do LocalStorage(projectPath).put(\a, \b, \c, value). You can also make the path the second parameter to the Singleton, so you can give it a friendly short name:

LocalStorage(\myProj, "/path/to/my/project");
LocalStorage(\myProj).at(...);

FWIW the big benefit of project-local storage is that everything can be tracked in git :slight_smile:

1 Like