In ML, all assignments are done using "pattern matching". val pattern = value; val w = (5, "cat"); val (x, y) = (5, "cat"); val (x, y) = (4, (5, 6)); val (x, y) = ((4, 5), 6); val ((x, _), y) = ((4, 5), 6); val (x, (_, y)) = (4, (5, 6)); val (x, (_, y)) = ((4, 5), (5, 6)); val [u, v] = [3, 4]; val [u, v] = [3, 4, 5, 6]; val u :: v = [3, 4, 5, 6]; val u :: v :: _ = [3, 4, 5, 6]; val u :: v :: w = [3, 4, 5, 6]; val (u, [v, w]) = (4, [5, 6]); val [u, v] = [(3, 4), (5, 6)]; val [u, (v, w)] = [(3, 4), (5, 6)]; val a = ("cat", [1, 2, 3], (4, 5)); val (b, c :: _, (_, d)) = a; Here is one reason why pattern matching is important. Remember that "parameter passing" is a form of assignment. For example, define f(x) = 3*x*x + 2*x + 5; Then the function call f(8); assigns x = 8. And the function call f(0); assigns x = 0. And y = -2; f(y); assigns x = y. Function definitions have "formal parameters" f(formal_parameter) = { ... } and function calls have "actual parameters" (also called "arguments"). f(actual_parameter); In a function call we always assign the actual parameters to the formal parameters, formal_parameter = actual_parameter So function calls are a kind of assignment. And in ML, all function calls are implemented using pattern matching of function call arguments with function definition parameters.