I don’t know about you, but I have the feeling that many people are interested by OCaml Batteries Included but don’t dare try it yet, due to the Alpha status and the fact that it’s not available for their favorite Linux distribution yet. Well, it’s probably a healthy level of caution.

Of course, just reading the manual is probably not the best way of getting a feeling of OCaml Batteries Included.

So I’ve decided to take measures. From time to time, I’ll add here a few samples of what you can do with OCaml Batteries Included and how you can do it.

For today, let’s start with displaying the contents of a file. You know, Unix’s cat or MS-DOS’s type.

open System, IO, File iter (fun x -> copy (open_in x) stdout) (args ())

That’s it. Three lines, one of them blank.

Now, for details: open System, IO, File opens three modules System (which contains all system-related functions, including input/output, file management, etc.), IO (the submodule of System containing all the operations on inputs and outputs), and File (the submodule of System containing all the necessary to open files for reading, writing, etc.).

Let’s move on to the last line. Function iter is defined in module Standard , which means that you don’t need to open any module to be able to use it. This function is a general imperative loop on enumerations. This is the equivalent of loop for-each in some languages. Perhaps I should detail what enumerations are: they are a read-and-forget data structure used pervasively in OCaml Batteries Included, and which replaces streams. By opposition to lists, arrays, etc., enumerations are built lazily and discarded as they are read, which makes them quite convenient for loops, or for accessing possibly huge sets of data — depending on your background, you may think of these either as streams (in OCaml and most languages) or as iterators (in Python, JavaScript and other dynamic languages). Oh, and for functional-minded people, don’t worry, your usual functional loops are available on enumerations, too. You can fold, map or unfold at will.

So, what does iter do? Well, if asked, OCaml will tell you that it has type ('a -> unit) -> 'a Enum.t -> unit . In other words, for any type 'a , this function takes as first argument a function (let’s call it f ), as second argument an enumeration of elements of type 'a and returns nothing. Function f itself should take as argument an element of type 'a and return nothing. In other words, iter takes a function which works on one element of type 'a and turns it into a function which works on a whole enumeration of elements of type 'a . Yep, it’s called a loop.

Before looking at the definition of the function, let’s take a look at the enumeration passed to iter : args () . Well, if we look at the documentation (for instance by using our on-line help), we may read

args(): An enumeration of the arguments passed to this program through the command line.

So, args () is your usual pair argc ;, argv (if you come from C) or args [] (if you come from Java). By opposition to Java, you don’t have to always put them in your program, if you don’t use them, and by opposition to both, it’s an enumeration, which makes more sense than an array, since you don’t need to modify them and since you always move forward among the arguments. Still, if you need it as an array, it’s available in a package. No more on this for the moment.

What’s left? Oh, yes, the function. As the code indicates, fun x -> copy (open_in x) stdout) is an anonymous function (also known as a “lambda” in a few languages). This function takes an argument x , the name of a file. Function copy , defined in module IO , takes two arguments, an input (a source of data) and an output (a sink of data), and copies the whole contents of the input into the output . The first argument here is open_in x , that is the result of applying function open_in to argument x . Function open_in , defined in module File , opens a file for reading. The result open_in x is therefore an input which lets us read the contents of file x . The second argument of copy is stdout , that is the standard output, that is the screen. In other words, fun x -> copy (open_in x) stdout) is a function which takes as argument the name of a file, opens that file and prints its contents on the screen. Note that everything is done lazily, so the contents is never completely present in memory. In other words, this works on files of theoretically unlimited length.

Bottom line: this utility reads all the files whose names are given on the command line and prints their content on the screen. In three lines of code.

Note that we could equally have written our utility

open System, IO, File iter f (args ()) where f x = copy (open_in x) stdout

or

open System, IO, File let f x = copy (open_in x) stdout;; iter f (args ())

or, in one line,

iter (fun x -> System.IO.copy (System.File.open_in x) stdout) (args ())

or a number of other variants.

Without Batteries Included, the same code, in OCaml, would have looked like

for i = 1 to Array.length Sys.argv - 1 do let file = open_in Sys.args.(i) in let ended = ref false in while not !ended try print_endline (input_line file) with End_of_file -> ended := true do done

Not much longer but definitely more complicated. Oh, and for fun, here’s the Java version:

import java.io.*; public class Demo { public static final void main(String args[]) { try { for(String x : args) { BufferedReader reader = new BufferedReader(new FileReader(x)); for(String read = reader.readLine(); read != null; read = reader.readLine()) System.out.println(read); } } catch (IOException e) { } } }

Note quite as short, note quite as simple and, in my humble opinion, not quite as nice.