Rewrite purely functionally
authorSiraaj Khandkar <siraaj@khandkar.net>
Tue, 17 Apr 2018 22:29:26 +0000 (18:29 -0400)
committerSiraaj Khandkar <siraaj@khandkar.net>
Tue, 17 Apr 2018 22:29:26 +0000 (18:29 -0400)
exercises/ch01/straight_line_program_interpreter.ml

index de4b921..534965f 100644 (file)
@@ -19,7 +19,8 @@ module Spl : sig
     | OpExp of exp * binop * exp
     | EseqExp of stm * exp
 
-  val maxargs : stm -> int
+  val maxargs : stm -> int option
+  (** Option because a program may not have any print statements at all. *)
 end = struct
   type id = string
 
@@ -45,31 +46,40 @@ end = struct
      * is 2.
      *)
     let maxargs stm =
-      let max = ref 0 in
-      let rec check_stm = function
+      let opt_max_update opt n =
+        match opt with
+        | None   -> Some n
+        | Some m -> Some (max m n)
+      in
+      let opt_max_merge a b =
+        match a, b with
+        | None  , None   -> None
+        | None  , b      -> b
+        | Some _, None   -> a
+        | Some _, Some n -> opt_max_update a n
+      in
+      let rec check_stm max_opt stm =
+        match stm with
         | PrintStm exps ->
-            let exps_length = List.length exps in
-            if exps_length > !max then max := exps_length else ();
-            List.iter exps ~f:check_exp
+            List.fold_left exps
+              ~init:(opt_max_update max_opt (List.length exps))
+              ~f:check_exp
         | AssignStm (_, e) ->
-            check_exp e
+            check_exp max_opt e
         | CompoundStm (s1, s2) ->
-            check_stm s1;
-            check_stm s2
-      and check_exp = function
-        | IdExp _ | NumExp _ -> ()
+            opt_max_merge (check_stm max_opt s1) (check_stm max_opt s2)
+      and check_exp max_opt exp =
+        match exp with
+        | IdExp _ | NumExp _ -> max_opt
         | OpExp (e1, _, e2) ->
-            check_exp e1;
-            check_exp e2
+            opt_max_merge (check_exp max_opt e1) (check_exp max_opt e2)
         | EseqExp (s, e) ->
-            check_stm s;
-            check_exp e
+            opt_max_merge (check_stm max_opt s) (check_exp max_opt e)
       in
-      check_stm stm;
-      !max
+      check_stm None stm
 end
 
-let spl_prog =
+let spl_prog_orig =
   (*  a := 5 + 3;
    *  b := (print(a, a - 1), 10 * a);
    *  print(b)
@@ -91,5 +101,24 @@ let spl_prog =
         )
     )
 
+let spl_prog_noprint =
+  (*  a := 5 + 3;
+   *  b := 10 * a
+   *)
+  Spl.CompoundStm
+    ( Spl.AssignStm
+        ("a", Spl.OpExp (Spl.NumExp 5, Spl.Plus, Spl.NumExp 3))
+    , Spl.AssignStm
+        ("b", Spl.OpExp (Spl.NumExp 10, Spl.Times, Spl.IdExp "a"))
+    )
+
 let () =
-  Printf.printf "maxargs: %d\n" (Spl.maxargs spl_prog)
+  let string_of_maxargs int_opt =
+    match int_opt with
+    | Some n -> string_of_int n
+    | None   -> "N/A"
+  in
+  Printf.printf "maxargs : spl_prog_orig -> %s\n"
+    (string_of_maxargs (Spl.maxargs spl_prog_orig));
+  Printf.printf "maxargs : spl_prog_noprint -> %s\n"
+    (string_of_maxargs (Spl.maxargs spl_prog_noprint))
This page took 0.031232 seconds and 4 git commands to generate.