CS118 Programming LanguagesLecture 10Contents
Tail RecursionOne can always program the equivalent of "while" with recursion. But actually calling recursive functions consumes stack, and eventually fails if the iteration goes on too long. So, tail recursion is optimized into an iteration.
% FILE: fact.m
% PURPOSE: compare with factorial.sml
function res = fact(n)
if n ~= ceil(n)
error('need integer');
elseif n < 0
error('need nonnegative');
elseif n == 0
res = 1;
else
res = n*fact(n-1);
end
----------------------------------
(* FILE: factorial.sml
* PURPOSE: demonstrate tail recursion
*)
fun fact(n: int): int =
if n = 0 then 1 else n*fact(n-1);
fact(0);
fact(5);
Function DefinitionIn ML a function is defined by giving a series of definitions for various types and values of the input. A collection of related functions are all defined at once using the "and" connective. Often a function will need a helper function to carry some data along (see len.sml). (* FILE: len.sml * PURPOSE: show helper function *) fun ct(lst): int = ct2(lst, 0) and ct2([], n: int): int = n | ct2(e::lst, n) = ct2(lst, n+1); ct([]); ct(String.explode "abc"); ct(1::2::3::nil); ct([1,2,3]); A Bigger ExampleSuppose you have a chessboard and a list of moves taken from a newspaper chess column. The moves are of the form (from, to) where the from and to are board positions. The positions are things like a1 and h8. Write a program to follow the moves and print out the final board. That is chess.sml. Now, consider checking that the moves are legal. Now consider letting the program pick the move. You are headed down the track of implementing a chess opponent. Proposition CompilerRemember the proposition grammar? We wrote a recursive C program to parse propositions. Write one in ML. To make it interesting, translate the ~&| proposition notation into the ?: C notation. That is ~mckeeman/src/ml/prop.sml. One can write an inverse translator ~mckeeman/src/ml/qmarkcolon.sml. All of this is dependent on grammars ~mckeeman/src/ml/*.cfg.
|