(* Programming Languages, James Wilcox, CSE341 *)
(* tail recursion: fact2 is tail-recursive, fact1 is not *)
fun fact1 n = if n=0 then 1 else n * fact1(n-1)
(*
fact1 4
=> 4 * fact1(3)
=> 4 * 3 * fact1(2)
=> 4 * 3 * 2 * fact1(1)
=> 4 * 3 * 2 * 1 * fact1(0)
=> 4 * 3 * 2 * 1 * 1
=> ..
=> 24
*)
fun fact2 n =
let fun aux(n,acc) = if n=0 then acc else aux(n-1,acc*n)
in
aux(n,1)
end
(*
fact2 4
=> aux(4,1)
=> aux(3,4)
=> aux(2,12)
=> aux(1,24)
=> aux(0,24)
=> 24
*)
(* more examples of making functions tail-recursive *)
fun sum1 xs =
case xs of
[] => 0
| i::xs' => i + sum1 xs'
fun sum2 xs =
let fun f (xs,acc) =
case xs of
[] => acc
| i::xs' => f(xs',i+acc)
in
f(xs,0)
end
fun rev1 xs =
case xs of
[] => []
| x::xs' => (rev1 xs') @ [x]
fun rev2 xs =
let fun aux(xs,acc) =
case xs of
[] => acc
| x::xs' => aux(xs', x::acc)
in
aux(xs,[])
end
fun inc_all1 xs =
case xs of
[] => []
| x :: xs => (x + 1) :: inc_all1 xs
fun inc_all2 xs =
let
fun loop (acc, xs) =
case xs of
[] => rev2 acc (* need to reverse! still constant space!!! *)
| x :: xs => loop (x + 1 :: acc, xs)
in
loop ([], xs)
end