reaching outside

Files & the world

Reading and writing files, directories, and other world-primitives — all marked >>, all with explicit failure handling.

Reading and writing

File operations read and write bytes. Both are marked >> and both can fail — Vision requires you to handle every failure case.

>> read the file at the path giving the bytes
    but if it isn't there, say "missing" and stop
    but if it can't be read, explain why and hand it on

>> write the bytes to the file at the output path
    but if it can't be written, explain why and hand it on

read the file at <path> giving <name> — reads the full file as bytes and binds the result to a name.

write <bytes> to the file at <path> — writes bytes to a file, creating it if it doesn't exist, overwriting if it does.

The atomic write pattern

Direct overwrites are not crash-safe: if the process dies mid-write, the file is corrupt. The safe pattern is write-to-temp, fsync, rename. Vision provides all three as verbs:

to publish, given the data and the path:
    the temp path is "{the path}.tmp"
    >> write the data to the file at the temp path
        but if it can't be written, explain why and hand it on
    >> make sure the file at the temp path is saved
        but if it can't be saved, explain why and hand it on
    >> rename the file at the temp path to the path
        but if it can't be renamed, explain why and hand it on

make sure the file is saved forces the data to durable storage (fsync). rename the file to the path performs an atomic swap on any POSIX filesystem — either the old file exists or the new one does, never neither.

Directories and remove

>> make the directory at the path
    but if it already exists, stop
    but if it can't be made, explain why and hand it on

>> !! remove the file at the path
    but if it isn't there, stop
    but if it can't be removed, explain why and hand it on

remove the file at <path> is marked >> !! because it cannot be undone. The !! makes this visible at the call site — a delete cannot look like a read.

Other primitives

All world-primitives follow the same pattern: marked >>, can fail, handled with but if.

  • Time>> ask the clock for the time giving the now
  • Environment>> ask the environment for "PATH" giving the path
  • Standard input>> read a line giving the input
  • Standard output>> say …
  • Randomness>> ask for a random number giving the n

The fact that say is a >> operation may surprise you. Standard output is a side effect — it modifies state outside the program. Vision treats it consistently with all other world-primitives.