I am trying to devise a pretty-printer for an Env.t type. An Env.t is simply a map from identifiers to values, i.e. a Value.t IdMap.t.
let pp fmt env =
let open Format in
fprintf fmt "[ @[<v 2>";
env |> IdMap.iter
(fun id val_ -> fprintf fmt "@[<hov 2>%s ->@ %a@]@." id Value.pp val_);
fprintf fmt "@]]"
This gives me this kind of results:
[ result -> 42.
succ -> <function>
x -> 42.
]
However, I was hoping to have an indentation of 2 spaces from the second line on. What am I doing wrong, and would using Fmt make my life easier?
let pp fmt = let open Format in function
| Nil -> pp_print_string fmt "nil"
| Boolean b -> pp_print_bool fmt b
| Number n -> pp_print_float fmt n
| Function _ -> pp_print_string fmt "<function>"
I think your boxing layout is wrong you need to write "@[<v2>[ " ⦠"]@]".
Currently you start you box after "[ " so itās going to set the ābox tabā at that column and will indent furthermore from there when you get on new lines.
In your case suppose we want to format a type int Map.Make(String).t, i.e. a map from string to int. We can do:
module Env = Map.Make(String)
(* This can format a seq of (string, int) pairs *)
let pp_t = Fmt.(braces (vbox (seq ~sep:semi (hbox (pair ~sep:comma string int)))))
(* This can format an int Env.t by converting it into a seq of (string, int) pairs *)
let pp_t formatter env = pp_t formatter (Env.to_seq env)
This gives us output like:
# #install_printer pp_t;;
# let env = ["a", 1; "b", 2; "c", 3] |> List.to_seq |> Env.of_seq;;
val env : int Env.t = {a, 1;
b, 2;
c, 3}
Not exactly what you wanted but you can adjust it somewhat more to your needs.
Neither of your suggested fixes worked on their own, but I finally figured out that it was entirely my fault. I used \n in Format.printf before that. Yes, I know that the documentation says not to, but I thought that at the top level out of any box it was fine. Now thinking twice I can see why it isnāt.
Iām surprised you need a benchmark to see wasted allocations in this program. But sorry I donāt write benchmarks I write real programs.
I often see programmers getting terrible performance out of their programs because they create little allocation hells for themselves.
This is a good educational example where useless allocations can be spotted and avoided without having to perform an elaborate monkey dance. Something the good working OCaml programmer routinely does.
Iām really tired of arguing with you and your continuous FUD, but anyway. Seq allocates, yes, but allocations are very short lived (consumed immediately) and thus will mostly impact the minor heap.
I find it funny to even talk about that in the context of Format, given the size of a formater and the complexity of its internal operations. Seq would probably be tiny on a profiler. The good programmer also measures, they donāt just guess based on their mental model ā unless you have the uncanny ability to predict where bottlenecks will actually be.
Now Iām off. Please stop inserting yourself in threads that donāt need your āhelpā.
Thereās no FUD, allocations exist, measuring is important but getting a feel for it also is.
However more importantly if you are tired of arguing with me then maybe donāt write to me in the first place.
Thatās kind of a funny comment to make, as a matter of fact you didnāt provide much help in this thread, except for derailing it in this pointless discussion.
FWIW, I have never found @dbuenzli 's interventions to be anything but helpful, even when it concerns things that he didnāt have obvious expert knowledge about. In the case of Format, I think he has expert knowledge.