Writing Files in Standard ML

Here’s the translation of the Go code to Standard ML, along with explanations in Markdown format suitable for Hugo:

Writing files in Standard ML follows similar patterns to the ones we saw earlier for reading.

(* Importing necessary modules *)
structure TextIO = TextIO
structure BinIO = BinIO

(* Function to handle errors *)
fun check (SOME e) = raise e
  | check NONE = ()

(* Main function *)
fun main () =
    let
        (* Writing a string to a file *)
        val _ = TextIO.writeFile "/tmp/dat1" "hello\nml\n"
        
        (* Opening a file for writing *)
        val outStream = TextIO.openOut "/tmp/dat2"
        
        (* Write byte slice *)
        val _ = BinIO.output (BinIO.openOut "/tmp/dat2", Word8Vector.fromList [0wx73, 0wx6F, 0wx6D, 0wx65, 0wx0A])
        
        (* Write string *)
        val _ = TextIO.output (outStream, "writes\n")
        
        (* Flush the stream *)
        val _ = TextIO.flushOut outStream
        
        (* Close the stream *)
        val _ = TextIO.closeOut outStream
        
        (* Using buffered output *)
        val bufferedStream = BinIO.openOut "/tmp/dat3"
        val _ = BinIO.output (bufferedStream, Word8Vector.fromList (map (fn c => Word8.fromInt (Char.ord c)) (String.explode "buffered\n")))
        val _ = BinIO.flushOut bufferedStream
        val _ = BinIO.closeOut bufferedStream
    in
        print "Files written successfully\n"
    end

(* Run the main function *)
val _ = main ()

To start, we write a string directly to a file using TextIO.writeFile.

For more granular writes, we open a file for writing using TextIO.openOut.

In Standard ML, there’s no built-in defer mechanism, so we need to manually close the file after we’re done writing.

We can write byte slices using BinIO.output and a Word8Vector.

For string writes, we use TextIO.output.

To ensure all writes are flushed to stable storage, we use TextIO.flushOut.

Standard ML doesn’t have a direct equivalent to Go’s bufio, but we can use BinIO for buffered I/O operations.

After writing to a buffered stream, we use BinIO.flushOut to ensure all buffered operations have been applied to the underlying writer.

To run the file-writing code, save it as writing-files.sml and use the Standard ML of New Jersey (SML/NJ) interpreter:

$ sml writing-files.sml
Files written successfully

Then check the contents of the written files:

$ cat /tmp/dat1
hello
ml
$ cat /tmp/dat2
some
writes
$ cat /tmp/dat3
buffered

Next, we’ll look at applying some of the file I/O ideas we’ve just seen to the standard input and output streams.