Recently I wrote an OCaml tool to analysis a large log file. To make it easy to read, I simplified the log format as
1 1 2 2 3 3 3 4 4 4 4 4
Each line of the log is a number between 0 and 10, my job is to analysis the count of each number, for example, the result above would be
Key: 1, Value: 2 Key: 2, Value: 2 Key: 3, Value: 3 Key: 4, Value: 5
Once again, to make it easy to read, I simplified the OCaml code as
open Core open Async let touch_tbl (imap: int Int.Map.t) (spot: int) : int Int.Map.t Deferred.t = let count = match Int.Map.find imap spot with | Some x -> x | None -> 0 in Int.Map.add imap ~key:spot ~data:(count + 1) |> return let get_dict (filename: string) : int Int.Map.t Deferred.t = let%bind lines = Reader.file_lines filename in let tbl = Int.Map.empty in Deferred.List.fold (List.map lines ~f:int_of_string) ~init:tbl ~f:(fun acc num -> touch_tbl acc num) let handle_file (filename: string) : unit Deferred.t = let%bind dict = get_dict filename in Int.Map.iter_keys dict ~f:(fun key -> print_string "Key: "; print_int key; print_string ", Value: "; print_int (Int.Map.find_exn dict key); print_newline (); ); return () let () = Command.async ~summary:"Analysis performance log" Command.Spec.( empty +> anon ("file" %: string) ) (fun filename () -> handle_file filename) |> Command.run
I compiled and ran the code, it works as expected:
$ corebuild -pkg async phonlog.native $ ./phonlog.native sim.log Key: 1, Value: 2 Key: 2, Value: 2 Key: 3, Value: 3 Key: 4, Value: 5
I was curious about:
|> returnat the end of the
touch_tblfunction, can I remove it in some other way?
get_dictfunction, I used to use
List.fold, but found I couldn’t compile until changed it to the
return ()at the end of the
handle_filefunction, can I remove it in some other way?
I used to write Java program, and I have to admit that I spent a lot of time to debug my code to make all the types ok.