Exit in Standard ML

Here’s an idiomatic Standard ML example that demonstrates the concept of program exit:

(* Exit.sml *)

(* Import the OS structure for exit functionality *)
structure OS = OS;

(* Define a function that will not be called *)
fun printMessage () = print "This will not be printed!\n";

(* Main program *)
val _ = (
  (* Register a cleanup function that won't be called *)
  OS.Process.atExit printMessage;
  
  (* Exit the program with status code 3 *)
  OS.Process.exit 3
);

This Standard ML program demonstrates how to exit a program with a specific status code. Let’s break down the code and its concepts:

  1. We import the OS structure, which provides system-level operations, including process management.

  2. We define a function printMessage that, if called, would print a message to the console.

  3. The main program is represented by the val _ = (...) expression. In Standard ML, the underscore _ is used when we don’t need to bind the result to a name.

  4. We use OS.Process.atExit printMessage to register our printMessage function to be called when the program exits normally. However, this function will not be called when we use OS.Process.exit.

  5. Finally, we call OS.Process.exit 3 to immediately terminate the program with an exit status of 3.

To compile and run this program:

  1. Save the code in a file named Exit.sml.
  2. Use an Standard ML compiler like MLton to compile the program:
$ mlton Exit.sml

This will create an executable file named Exit.

  1. Run the program:
$ ./Exit
$ echo $?
3

You’ll notice that no output is produced, and the exit status is 3.

Important notes:

  • Unlike some other languages, Standard ML doesn’t use the return value of a main function to determine the exit status. Instead, we explicitly call OS.Process.exit with the desired status code.
  • The atExit function registers cleanup actions for normal program termination. However, when using OS.Process.exit, these cleanup actions are not performed.
  • Standard ML doesn’t have a direct equivalent to Go’s defer keyword. The atExit function provides similar functionality for program-wide cleanup, but it doesn’t work on a per-function basis like Go’s defer.

This example demonstrates how to control program exit in Standard ML, which is a crucial concept in systems programming and error handling.