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:
-
|> return
at the end of thetouch_tbl
function, can I remove it in some other way? -
Deferred.List.fold
in theget_dict
function, I used to useList.fold
, but found I couldn’t compile until changed it to theDeferred
. -
return ()
at the end of thehandle_file
function, 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.