Functions in Standard ML

Functions are central in Standard ML. We’ll learn about functions with a few different examples.

(* Here's a function that takes two ints and returns their sum as an int. *)
fun plus (a : int, b : int) : int =
    a + b

(* Standard ML doesn't require explicit returns. The value of the last 
   expression in a function is automatically returned. *)

(* In Standard ML, we can define multiple parameters with the same type 
   more concisely using a tuple pattern. *)
fun plusPlus (a : int, b : int, c : int) : int =
    a + b + c

(* The main function in Standard ML is typically not explicitly defined. 
   Instead, we can write our code at the top level. *)

(* Call a function just as you'd expect, with name(args). *)
val res = plus(1, 2)
val _ = print("1+2 = " ^ Int.toString(res) ^ "\n")

val res = plusPlus(1, 2, 3)
val _ = print("1+2+3 = " ^ Int.toString(res) ^ "\n")

To run this Standard ML program, you would typically save it to a file (e.g., functions.sml) and then use an SML interpreter or compiler. For example, using the Standard ML of New Jersey (SML/NJ) system:

$ sml functions.sml
1+2 = 3
1+2+3 = 6

There are several other features to Standard ML functions. One is pattern matching, which we’ll look at next.

Standard ML has some key differences from many other languages:

  1. Function definitions use the fun keyword.
  2. Type annotations are optional but commonly used for clarity.
  3. The last expression in a function is automatically returned.
  4. There’s no explicit main function; top-level expressions are executed in order.
  5. String concatenation uses the ^ operator.
  6. Printing is typically done with the print function, which only handles strings.

These examples demonstrate basic function definitions and calls in Standard ML, showing how to work with multiple parameters and return values.