The following function implements the factorial function. The environment diagram represents the processing of fact 3 just as it hits the base case. Notice that the bindings of n to 2 and 3 are not garbage and must be kept around so that they can be applied to the result of the recursive call.
let
fun fact(n:int):int =
if n = 1 then 1
else fact(n - 1) * n
in
fact 3
end
|
![]() |
This version of the factorial function is tail recursive. Notice that this time, the bindings from the previous calls to tfact are garbage as soon as they do their recursive call. The diagram shows how the recursive call does not increase its memory usage linearly with the number of recursive calls (like the previous example did.)
let
fun tfact(n:int, acc:int):int =
if n = 1 then 1
else tfact(n - 1, n * acc)
in
tfact(3, 1)
end
| ![]() |
The following example shows how refs are represented in the environment diagrams:
let val y = ref 1 val z = ref y val a = ref y in 5 end | ![]() |
Consider the following code which is identical but reassigns what some of the references point to. Notice how the diagram changes.
let val y = ref 1 val z = ref y val a = ref y val () = z := ref 5 val () = a := !z in 5 end | ![]() |