# Format module from the Standard Library

**URL:** <https://discuss.ocaml.org/t/format-module-from-the-standard-library/2254>\
**Category:** Learning\
**Tags:** format\
**Created:** [July 9, 2018, 1:46pm UTC](https://discuss.ocaml.org/t/format-module-from-the-standard-library/2254 "2018-07-09T13:46:22Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![cloudyhug](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/cloudyhug/32/2399_2.png) [@cloudyhug](https://discuss.ocaml.org/u/cloudyhug)\
**Post date:** [July 9, 2018, 1:46pm UTC](https://discuss.ocaml.org/t/format-module-from-the-standard-library/2254/1 "2018-07-09T13:46:22Z")

</div>

Hello everyone. Does any of you know where I can find a decent tutorial for the OCaml Format module ? I cannot figure out how to use it, and the few things I have found are the documentation and the official tutorial, which are explicit but not clear at all. I have spent the last 30 minutes trying to understand it, in vain.

Thanks a lot for your answers.

---

<div class="post-metadata">

**Author:** ![Drup](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/drup/32/35_2.png) [@Drup](https://discuss.ocaml.org/u/Drup)\
**Post date:** [July 9, 2018, 2:09pm UTC](https://discuss.ocaml.org/t/format-module-from-the-standard-library/2254/2 "2018-07-09T14:09:45Z")

</div>

I would recommend reading this blog post: [https://cedeela.fr/format-all-the-data-structures.html](https://cedeela.fr/format-all-the-data-structures.html)

For understanding boxes, see [https://ocaml.org/learn/tutorials/format.html](https://ocaml.org/learn/tutorials/format.html)

---

<div class="post-metadata">

**Author:** ![cloudyhug](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/cloudyhug/32/2399_2.png) [@cloudyhug](https://discuss.ocaml.org/u/cloudyhug)\
**Post date:** [July 9, 2018, 2:43pm UTC](https://discuss.ocaml.org/t/format-module-from-the-standard-library/2254/3 "2018-07-09T14:43:21Z")

</div>

I’ll have a look at it. Thanks !

---

<div class="post-metadata">

**Author:** ![mjambon](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/mjambon/32/6180_2.png) [@mjambon](https://discuss.ocaml.org/u/mjambon)\
**Post date:** [July 9, 2018, 5:42pm UTC](https://discuss.ocaml.org/t/format-module-from-the-standard-library/2254/4 "2018-07-09T17:42:19Z")

</div>

If that’s an option for you, I’d suggest using [easy-format](https://github.com/mjambon/easy-format). There’s a [complete example here](https://mjambon.github.io/mjambon2016/easy_format_example.html) with various ways to format the same thing.

---

<div class="post-metadata">

**Author:** ![jhaberku](https://avatars.discourse-cdn.com/v4/letter/j/5f8ce5/32.png) [@jhaberku](https://discuss.ocaml.org/u/jhaberku)\
**Post date:** [July 10, 2018, 2:34pm UTC](https://discuss.ocaml.org/t/format-module-from-the-standard-library/2254/5 "2018-07-10T14:34:13Z")

</div>

Check out [this paper](https://hal.archives-ouvertes.fr/hal-01503081/file/format-unraveled.pdf), whose purpose is to explain and document the module.

---

<div class="post-metadata">

**Author:** ![rizo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/rizo/32/93_2.png) [@rizo](https://discuss.ocaml.org/u/rizo)\
**Post date:** [July 10, 2018, 2:55pm UTC](https://discuss.ocaml.org/t/format-module-from-the-standard-library/2254/6 "2018-07-10T14:55:09Z")

</div>

I vividly remember how strange it looked the first time I tried using it. Other people recommended some resources to understand how to used it and how the boxing model works. I strongly recommend using the [fmt](http://erratique.ch/software/fmt) library that abstracts a lot of complexity of the `Format` module.

---

<div class="post-metadata">

**Author:** ![Drup](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/drup/32/35_2.png) [@Drup](https://discuss.ocaml.org/u/Drup)\
**Post date:** [July 10, 2018, 6:14pm UTC](https://discuss.ocaml.org/t/format-module-from-the-standard-library/2254/7 "2018-07-10T18:14:30Z")

</div>

I would actually recommend _against_ `easy-format`. `Fmt` gives you a better API, but without adding layers upon layers of indirection and a direct compatibility with all the printers out there.

Format has a terrible API, but you don’t have to use it nowadays, Fmt and CCFormat are 100% compatible, including formatting strings, and with excellent APIs.

---

<div class="post-metadata">

**Author:** ![mjambon](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/mjambon/32/6180_2.png) [@mjambon](https://discuss.ocaml.org/u/mjambon)\
**Post date:** [July 10, 2018, 8:59pm UTC](https://discuss.ocaml.org/t/format-module-from-the-standard-library/2254/8 "2018-07-10T20:59:36Z")

</div>

I wonder what you use `Format` and descendants for?

I made easy-format around 2010 so I could pretty-print json and code in general, like a programmer would. Printing things like this using just `Format` was incredibly tricky:

```
{
  "field": {
    "number": 123,
    "text": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
  }
}

```

This requires a box with negative indentation for the `}` to be aligned with `"field": {` rather than with `"text":`. I don’t think it’s something the user should have to learn or understand, so it’s one of the styling options. The following style is also something that we don’t see often in popular json pretty-printers but it’s one of the built-in styles:

```
[
  [
    12345, 12345, 12345, 12345, 12345, 12345, 12345, 12345, 12345, 12345,
    12345, 12345, 12345, 12345, 12345, 12345, 12345
  ],
  [
    { "x": 0, "y": 100 },
    12345,
    12345,
    12345,
    12345,
    12345,
    12345,
    12345,
    12345,
    12345,
    12345,
    12345,
    12345
  ]
]

```

All the material within square brackets `[...]` in the example above use the same built-in style. You can try this by running `ydump` on arbitrary json; it’s provided by the `yojson` package.

It’s great to see initiatives to offer a libraries which work better in different contexts or overall.

> [@Drup](#):
>
> I would actually recommend _against_ `easy-format` . `Fmt` gives you a better API, but without adding layers upon layers of indirection

I’m not sure what you mean by “layers upon layers of indirection”. Would you like to elaborate? (I haven’t used `Fmt`, which came later, and so I’m genuinely curious, not just sad because I’m the author of easy-format)

---

<div class="post-metadata">

**Author:** ![Drup](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/drup/32/35_2.png) [@Drup](https://discuss.ocaml.org/u/Drup)\
**Post date:** [July 11, 2018, 8:52am UTC](https://discuss.ocaml.org/t/format-module-from-the-standard-library/2254/9 "2018-07-11T08:52:01Z")

</div>

> [@mjambon](#):
>
> This requires a box with negative indentation for the `}` to be aligned with `"field": {` rather than with `"text":` .

No it doesn’t, Just close the box before closing the parens:

```ocaml
# Fmt.pr 
     {|@[<v2>"%s": {@ %a@]@ }|} 
     "foo" 
     Fmt.(list ~sep:cut string) ["aaa"; "bbb" ; "ccc"];;
"foo": {
  aaa
  bbb
  ccc
}

```

You almost never need negative indentation with format. If you do, it’s more likely than your boxes are in the wrong places.

Honestly, there is nothing really easy about `easy-format`. The API is not particularly intuitive, the layout specification is not particularly easier to use and it looses all the free-form combinators from `Format`.

---

<div class="post-metadata">

**Author:** ![keleshev](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/keleshev/32/3779_2.png) [@keleshev](https://discuss.ocaml.org/u/keleshev)\
**Post date:** [July 11, 2018, 9:17am UTC](https://discuss.ocaml.org/t/format-module-from-the-standard-library/2254/10 "2018-07-11T09:17:44Z")

</div>

Not a tutorial, but you might find it helpful to see some examples of Format usage.

Here’s a pretty-printer for a small subset of XML:

> <https://gist.github.com/keleshev/5af7502e6810b8986d9f5332e7e8a795>

A pretty-printer for a subset of JavaScript:

> <https://github.com/Virum/compiler/blob/28e807b842bab5dcf11460c8193dd5b16674951f/JavaScript.ml#L112>

A pretty-printer for a subset of Python:

> <https://github.com/Virum/compiler/blob/master/Python.ml#L130>

Personally, I like the Format module very much and never had to reach for another library, but I remember that it was tricky to wrap my head around when I just started to use it.

---

<div class="post-metadata">

**Author:** ![Armael](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/armael/32/1223_2.png) [@Armael](https://discuss.ocaml.org/u/Armael)\
**Post date:** [July 11, 2018, 9:19am UTC](https://discuss.ocaml.org/t/format-module-from-the-standard-library/2254/11 "2018-07-11T09:19:28Z")

</div>

Maybe these examples should be added to the manual of Format?

---

<div class="post-metadata">

**Author:** ![bluddy](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/bluddy/32/104_2.png) [@bluddy](https://discuss.ocaml.org/u/bluddy)\
**Post date:** [July 11, 2018, 2:49pm UTC](https://discuss.ocaml.org/t/format-module-from-the-standard-library/2254/12 "2018-07-11T14:49:06Z")

</div>

To me, the best tip for using Format is to avoid the functions and use the printf symbols instead. It just tends to work out much better that way.

---

<div class="post-metadata">

**Author:** ![mjambon](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/mjambon/32/6180_2.png) [@mjambon](https://discuss.ocaml.org/u/mjambon)\
**Post date:** [July 11, 2018, 6:11pm UTC](https://discuss.ocaml.org/t/format-module-from-the-standard-library/2254/13 "2018-07-11T18:11:42Z")

</div>

> [@Drup](#):
>
> No it doesn’t, Just close the box before closing the parens:

Well, the point here is to print `"foo":` on the left-hand-side independently from the right-hand-side, which may or may not involve curly braces.

> [@Drup](#):
>
> Honestly, there is nothing really easy about `easy-format` . The API is not particularly intuitive, the layout specification is not particularly easier to use and it looses all the free-form combinators from `Format` .

Thanks for your input. I’m sure it’s not easy to get started with it but readability was the primary concern. For reference, people can look at the [source code of the json pretty-printer that comes with yojson](https://github.com/mjambon/yojson/blob/master/lib/pretty.ml). I haven’t touched this code—or any proper pretty-printer for that matter—in 8 years and I still find this somewhat readable.

---

<div class="post-metadata">

**Author:** ![keleshev](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/keleshev/32/3779_2.png) [@keleshev](https://discuss.ocaml.org/u/keleshev)\
**Post date:** [July 20, 2018, 11:08am UTC](https://discuss.ocaml.org/t/format-module-from-the-standard-library/2254/14 "2018-07-20T11:08:04Z")

</div>

@mjambon regarding your JSON example, it is possible to format each key and value independently and without negative indentation. Here’s an example:

```ocaml
let fprintf, printf, list = Format.(fprintf, printf, pp_print_list)

let rec format_json f = function
  | `Number n ->
      fprintf f "%d" n
  | `Object pairs ->
      fprintf f "{@;<0 2>@[<v 0>%a@]@,}"
        (list ~pp_sep:(fun f () -> fprintf f ",@ ") format_key_value) pairs

and format_key_value f (key, value) =
  fprintf f "%s: %a" key format_json value

let example =
  `Object [
    "field", `Object [
      "number", `Number 123;
      "text", `Number 10000000000000000;
    ];
  ]

let () =
  printf "@[<v 0>%a@]" format_json example

```

Output:

```auto
{
  field: {
    number: 123,
    text: 10000000000000000
  }
}

```

The trick is that the zero-indentation box is inside the curly braces:

![image](https://us1.discourse-cdn.com/flex020/uploads/ocaml/original/2X/d/d58958fc8e4ff3a53bbf0c78df255a32dc8a697c.png)

However, I would say, the solution is non-obvious.

---

<div class="post-metadata">

**Author:** ![keleshev](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/keleshev/32/3779_2.png) [@keleshev](https://discuss.ocaml.org/u/keleshev)\
**Post date:** [July 20, 2018, 11:16am UTC](https://discuss.ocaml.org/t/format-module-from-the-standard-library/2254/15 "2018-07-20T11:16:48Z")

</div>

My one problem with Format, is that you can’t, for example, add a trailing comma in an list, depending whether the layout is horizontal or vertical. For example, I want this horizontal layout:

```auto
[foo, bar, baz]

```

Collapse into the following vertical layout:

```auto
[ 
  foo,
  bar,
  baz,
]

```

Notice the last trailing comma.

Suggestions welcome.

---

<div class="post-metadata">

**Author:** ![Drup](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/drup/32/35_2.png) [@Drup](https://discuss.ocaml.org/u/Drup)\
**Post date:** [July 20, 2018, 11:36am UTC](https://discuss.ocaml.org/t/format-module-from-the-standard-library/2254/16 "2018-07-20T11:36:30Z")

</div>

I remember thinking about adding a function `pp_print_string_or_nl : Format.formatter -> t -> unit` which would act more or less like `pp_print_break` and either print the given string, or split the line. I remember being unsatisifed with the API (and the fact that your use case doesn’t exactly fit prove that it was not good enough). If you come up with a good API, this should not be difficult to implement.

---

<div class="post-metadata">

**Author:** ![keleshev](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/keleshev/32/3779_2.png) [@keleshev](https://discuss.ocaml.org/u/keleshev)\
**Post date:** [July 20, 2018, 12:36pm UTC](https://discuss.ocaml.org/t/format-module-from-the-standard-library/2254/17 "2018-07-20T12:36:58Z")

</div>

How about this:

```auto
val pp_print_explicit_break : formatter -> no_break:string -> break:(string * string) -> unit

```

Which is similar to `pp_print_break`, but takes strings instead of integers? The tuple corresponds to text before and after break.

`pp_print_explicit_break ppf ~no_break:"" ~break:("", " ")` corresponds to `pp_print_break ppf 0 4`,  
`pp_print_explicit_break ppf ~no_break:" " ~break:("", "")` corresponds to `pp_print_break ppf 1 0`,  
while an optional trailing comma could be denoted as:

```ocaml
pp_print_explicit_break ppf ~no_break:"" ~break:(",", "")

```

Maybe it could have a format string shortcut, like `pp_print_break` does. For example `@;<"" "" " ">` for `@;<0 4>`.

Not sure. This does not strike me as particularly elegant.

---

<div class="post-metadata">

**Author:** ![Drup](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/drup/32/35_2.png) [@Drup](https://discuss.ocaml.org/u/Drup)\
**Post date:** [July 20, 2018, 12:59pm UTC](https://discuss.ocaml.org/t/format-module-from-the-standard-library/2254/18 "2018-07-20T12:59:51Z")

</div>

That’s certainly seems sufficiently generic, and I think it’s the best you can provide given `Format`'s layout engine. It’s indeed not fantastically elegant, but not all functions are beautifull programming perls. 🙂

I’m not sure a syntax is really needed.

If you want to take a shot at it, I’m fairly certain this would be easy to add (just by looking at break and generalizing it). You can then express the other break/cut functions in term of it.

---

<div class="post-metadata">

**Author:** ![mjambon](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/mjambon/32/6180_2.png) [@mjambon](https://discuss.ocaml.org/u/mjambon)\
**Post date:** [July 20, 2018, 5:48pm UTC](https://discuss.ocaml.org/t/format-module-from-the-standard-library/2254/19 "2018-07-20T17:48:09Z")

</div>

@keleshev I definitely forgot, but the original conclusion that a negative indentation was needed may have come from the following.

For json objects, we should have a style that outputs either this (a):

```
{
  field: {number: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", text: "a"}
}

```

or this (b):

```
{
  field: {
    number: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    text: "aaaaaaaaaaaaaaaaaa"
  }
}

```

but not this (c):

```
{
  field: {
    number: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", text: "a"
  }
}

```

These outputs were produced by modifying your original code, using an `hv` box for the list of fields instead of just `v`, and changing the leaf values to strings of different lengths. Editing the aaaa strings for case (c) gives:

```
let fprintf, printf, list = Format.(fprintf, printf, pp_print_list)

let rec format_json f = function
  | `String s ->
      fprintf f "%S" s
  | `Object pairs ->
      fprintf f "{@;<0 2>@[<hv 0>%a@]@,}"
        (list ~pp_sep:(fun f () -> fprintf f ",@ ") format_key_value) pairs

and format_key_value f (key, value) =
  fprintf f "%s: %a" key format_json value

let example =
  `Object [
    "field", `Object [
      "number", `String "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
      "text", `String "a";
    ];
  ]

let () =
  printf "@[<v 0>%a@]" format_json example
```

---

<div class="post-metadata">

**Author:** ![keleshev](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/keleshev/32/3779_2.png) [@keleshev](https://discuss.ocaml.org/u/keleshev)\
**Post date:** [August 23, 2018, 1:54pm UTC](https://discuss.ocaml.org/t/format-module-from-the-standard-library/2254/20 "2018-08-23T13:54:09Z")

</div>

FYI, there’s now a PR for the “pp\_print\_explicit\_break” feature: [https://github.com/ocaml/ocaml/pull/2002](https://github.com/ocaml/ocaml/pull/2002)

Feedback is welcome.

[Next page](https://discuss.ocaml.org/t/format-module-from-the-standard-library/2254.md?page=2)
