Directories in Standard ML

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

(* Standard ML doesn't have a built-in directory manipulation module,
   so we'll use the SMLofNJ.OS.FileSys module for file system operations *)
structure FileSys = SMLofNJ.OS.FileSys

(* Helper function to handle errors *)
fun check result =
    case result of
        SOME err => raise err
      | NONE => ()

(* Helper function to create an empty file *)
fun createEmptyFile name =
    let
        val outStream = TextIO.openOut name
    in
        TextIO.closeOut outStream
    end

(* Main function *)
fun main () =
    let
        (* Create a new sub-directory in the current working directory *)
        val _ = check (FileSys.mkDir "subdir")

        (* Create files and directories *)
        val _ = createEmptyFile "subdir/file1"
        val _ = check (FileSys.mkDir "subdir/parent")
        val _ = check (FileSys.mkDir "subdir/parent/child")
        val _ = createEmptyFile "subdir/parent/file2"
        val _ = createEmptyFile "subdir/parent/file3"
        val _ = createEmptyFile "subdir/parent/child/file4"

        (* List directory contents *)
        val dirStream = FileSys.openDir "subdir/parent"
        fun listDir () =
            case FileSys.readDir dirStream of
                SOME entry => (print (" " ^ entry ^ " " ^
                                     Bool.toString (FileSys.isDir entry) ^ "\n");
                               listDir ())
              | NONE => FileSys.closeDir dirStream

        val _ = (
            print "Listing subdir/parent\n";
            listDir ()
        )

        (* Change directory *)
        val _ = FileSys.chDir "subdir/parent/child"
        val currentDir = FileSys.getDir ()
        val _ = print ("Current directory: " ^ currentDir ^ "\n")

        (* Change back to the original directory *)
        val _ = FileSys.chDir "../../.."

        (* Recursive directory traversal *)
        fun visit path =
            let
                val isDir = FileSys.isDir path
                val _ = print (" " ^ path ^ " " ^ Bool.toString isDir ^ "\n")
                val dirStream = if isDir then FileSys.openDir path else raise Fail "Not a directory"
                fun traverse () =
                    case FileSys.readDir dirStream of
                        SOME entry =>
                            let
                                val fullPath = OS.Path.joinDirFile {dir = path, file = entry}
                            in
                                visit fullPath;
                                traverse ()
                            end
                      | NONE => FileSys.closeDir dirStream
            in
                if isDir then traverse () else ()
            end

        val _ = (
            print "Visiting subdir\n";
            visit "subdir"
        )
    in
        ()
    end

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

This Standard ML code demonstrates directory operations similar to the original Go example. Here are some key differences and explanations:

  1. Standard ML doesn’t have a built-in module for directory operations, so we use SMLofNJ.OS.FileSys from the Standard ML of New Jersey implementation.

  2. Error handling is done using pattern matching on SOME err and NONE instead of explicit error checks.

  3. File creation is done using TextIO.openOut and TextIO.closeOut instead of os.WriteFile.

  4. Directory listing is implemented using FileSys.openDir and FileSys.readDir in a recursive function.

  5. Changing directories is done with FileSys.chDir.

  6. The recursive directory traversal is implemented using a custom visit function that uses FileSys.openDir and FileSys.readDir.

  7. Standard ML doesn’t have an exact equivalent of Go’s defer, so cleanup operations are handled manually.

To run this program, you would typically save it as a .sml file and use an Standard ML interpreter or compiler to execute it. The exact command might vary depending on your Standard ML implementation.

$ sml directories.sml

This code provides a similar functionality to the original Go example, demonstrating directory operations in Standard ML.