#utop_prompt_dummy let _ = UTop.set_show_box false (* Local Bindings *) let silly1 (z : int) = let x = if z > 0 then z else 34 in let y = x + 9 in if x > y then x * 2 else y * y let silly2 () = (* poor style, just showing let expressions are expressions *) let x = 1 in (let x = 2 in x+1) + (let y = x+2 in y+1) let celsius_of_fahrenheit (tempF : float) = (tempF -. 32.0) *. 5.0 /. 9.0 (* example where let expressions probably make code more readable even though no computations are repeated *) (* will have better ways to do this with variant types *) let is_first_warmer ((temp1 : float), (is_celsius1 : bool), (temp2 : float), (is_celsius2 : bool)) = let temp1C = if is_celsius1 then temp1 else celsius_of_fahrenheit temp1 in let temp2C = if is_celsius2 then temp2 else celsius_of_fahrenheit temp2 in temp1C > temp2C (* example where we avoid repeating a computation, but it would not matter much *) let rec squaring_sequence ((x:float), (n:int)) = if n=0 then [] else let sq = x *. x in sq :: squaring_sequence(sq,n-1) let rec range ((lo : int),(hi : int)) = if lo < hi then lo :: range (lo + 1, hi) else [] let nats_upto1 (x : int) = range (0,x) let nats_upto2 (x : int) = let rec range ((lo : int),(hi : int)) = if lo < hi then lo :: range (lo + 1,hi) else [] in range (0,x) let nats_upto3 (x : int) = let rec loop (lo : int) = (* loop is NOT a special word, could call it fred *) if lo < x then lo :: loop (lo + 1) else [] in loop 0 (* badly named: evaluates to 0 on empty list *) let rec bad_max (xs : int list) = if xs = [] then 0 (* bad semantic style *) else if List.tl xs = [] then List.hd xs else if List.hd xs > bad_max (List.tl xs) then List.hd xs else bad_max (List.tl xs) let rec better_max (xs : int list) = if xs = [] then 0 (* bad semantic style *) else if List.tl xs = [] then List.hd xs else let tl_max = better_max (List.tl xs) in if List.hd xs > tl_max then List.hd xs else tl_max let rec good_max1 (xs : int list) = if xs = [] then None else let tl_ans = good_max1 (List.tl xs) in if not (tl_ans = None) && Option.get tl_ans > List.hd xs then tl_ans else Some (List.hd xs) let good_max2 (xs : int list) = if xs = [] then None else let rec max_nonempty (xs : int list) = if List.tl xs = [] (* xs better not be [] *) then List.hd xs else let tl_ans = max_nonempty (List.tl xs) in if List.hd xs > tl_ans then List.hd xs else tl_ans in Some (max_nonempty xs) (*let does_not_typecheck = (good_max1 [3;4;2]) + 4*) (* A t option is *not* an int *) let risky_but_works = (Option.get (good_max1 [3;4;2])) + 2 (* type-checks, raises exception *) (* let risky_and_fails = (Option.get (good_max1 [])) + 2*) let propagate_option = let x = good_max1 [3;4;2] in if Option.is_some x then Some ((Option.get x) + 2) else None (* benefits of no mutation *) (* does not matter if returns an alias *) let sort_pair (pr : int * int) : int * int = if fst pr < snd pr then pr (* (fst pr, snd pr) *) else (snd pr, fst pr) (* naturally and efficiently introduces sharing and we don't care *) let rec append ((xs : 'a list), (ys : 'a list)) = if xs = [] then ys else List.hd xs :: append (List.tl xs, ys)