Zipping Collections in OCaml
Many programming languages have a function for combining the elements of multiple collections (e.g. arrays or lists) together. Typically this function is named zip
. Here’s an example from Haskell:
zip [1, 2] ['a', 'b'] -- => [(1, 'a'), (2, 'b')]
When I’ve started to learn OCaml it took a me a while to find the matching function, as it was named differently - namely combine
. Here’s how it works for lists:
List.combine [1;2;3] [4;5;6];;
- : (int * int) list = [(1, 4); (2, 5); (3, 6)]
(* notice the super informative error message *)
List.combine [1;2;3] [4;5;6;7];;
Exception: Invalid_argument "List.combine".
There’s also Array.combine
, which work identically for arrays:
Array.combine [|1;2;3|] [|4;5;6|];;
- : (int * int) array = [|(1, 4); (2, 5); (3, 6)|]
One thing to note is that List.combine
(and Array.combine
) will raise an exception if the two lists don’t have the same size. Whether this is good or bad I’ll leave to you to decide. Personally, I prefer the behavior where the length of the shorter list determines the length of the result. The popular library Containers (it packs many extensions to the standard library), features just the right function for this:
CCList.combine_shortest [1;2;3] [4;5;6;7];;
- : (int * int) list = [(1, 4); (2, 5); (3, 6)]
There’s also CCList.combine
, which is basically a more efficient version of List.combine
from the standard library.
The popular Base library has similar functions to the those in the standard library, but there they are named List.zip
, List.zip_exn
, Array.zip
and Array.zip_exn
. Both of the require the lists/arrays to be of the same length, but the first returns an error type and the second raises an exception.
The reverse operation of zipping/combining is named split
in the standard library:
List.split [(1, 4); (2, 5); (3, 6)];;
- : int list * int list = ([1; 2; 3], [4; 5; 6])
In Base
it’s named unzip
.
You might be wondering at this point how does one discover the APIs they need in OCaml. I can recommend a few options:
- Sherlocode and Sherlodoc are great way to search for OCaml code usages and explore APIs. Typically I’d search for something in Sherlodoc first and then I’d look for example usages with Sherlocode.
- Spend some quality time with the Standard API’s documentation
- Spend some time with the API documentation for Containers
- Explore the Base APIs
Googling also works, of course. Most of it, however, will just lead you to some StackOverflow/OCaml Discourse discussion, that will require you to do some follow-up API exploration anyways.
As you can see - you’ve got plenty of options for zipping collections in OCaml, even if they require a bit of discovery time. That’s all I have for you today! Keep hacking!