(* lecture 6: higher-order functions, defining operators, exceptions, print *) (* Applies function F to each element of the given list [a,b,c,...], producing a new list [F(a),F(b),F(c),...]. *) fun map(F, []) = [] | map(F, first::rest) = F(first) :: map(F, rest); (* Calls function P on each element of the given list [a,b,c,...]; P is an inclusion test that returns either true or false. The elements for which P returns true are kept; the others discarded. *) fun filter(P, []) = [] | filter(P, first::rest) = if P(first) then first :: filter(P, rest) else filter(P, rest); (* test data *) val test = [4, ~5, 6, ~19, ~42, 31, ~2]; (* we'll implement 'reduce' on Wednesday. fun reduce(F, L) = ... *) (* x ^^ y = x raised to the y power. Defining our own operator. *) infix ^^; (* one way to implement ^^. fun op ^^(base, 0) = 1 | op ^^(base, exp) = base * op ^^(base, exp-1); *) (* Second way to implement ^^. Produces base raised to the exp power. Assumes exp is non-negative. *) fun _ ^^ 0 = 1 | base ^^ exp = base * (base ^^ (exp-1)); (* Defining an exception type to raise when a number is not negative. *) exception NonPositive; (* Implementation of fibonacci that raises (throws) an exception when the integer passed is 0 or less. *) fun fibonacci(1) = 1 | fibonacci(2) = 1 | fibonacci(n) = if n < 1 then raise NonPositive else fibonacci(n - 1) + fibonacci(n - 2); (* An example of a function that calls fibonacci but handles (catches) any NonPositive exception that is raised, returning -42 in that case. *) fun foo(n) = 4 * fibonacci(n) handle NonPositive(s) => ~42 ; (* Produces the larger of the two values passed. An example of using the print function. *) fun max(a, b) = if a > b then ( print("a is bigger\n"); a ) else ( print("a is NOT bigger\n"); b );