Stubbed Toes: Getting started with…. OCaml on OS X

Why am I learning some OCaml when I am trying to focus on Clojure?

When there I don’t understand an underlying part of a technology that I use I mentally mark it as “good magic” and then feel bad about it until the guilt drives me to address the lack of understanding. When I kind of understand it it moves to the burrito stage where I’ve read or listened enough about it to offer an analogy and be credibly wrong. Burrito knowledge is uncertain but well intentioned navigational advice: you only dispense it to people you feel too compelled to help, or to people you don’t mind accidentally screwing. This is a dangerous stage and any time I speak from this stage I caveat it with “I’m probably wrong”.

I recently moved my understanding of functional data structures into the burrito stage and while I can’t recall to cite all of the readings I think the Javelin presentation triggered. So I am currently trying to get started reading Chris Okasaki’s book Purely Functional Data Structures. I have heard good things about this book, I like books, and it seems to contain the information required to move my knowledge of functional data structures out of burrito territory. Unfortunately, it seems to require a fairly solid knowledge of ML (there are Haskell translations for most things in the back but I’m not comfortable getting the intended thoughts through a second translation from ML to Haskell as interpreted by my meh level Haskell understanding). I still want to know about Purely Functional Data Structures, so now I am taking a quick detour (famous last words) into ML, specifically OCaml. I chose OCaml vs SML based on the comparison described here and probably because I’ve read about OCaml more than SML (solid work Jane Street in terms of mindshare management) and it seems like it’ll be serviceable for my purposes. I wanted to document some of the random pains of getting started with the tutorial with OCaml on a Macbook Pro that didn’t have full answers elsewhere, so this is mostly installation guide and only incidentally a very bad micro-intro to OCaml.

How is that going so far?

First let’s install OCaml. The advice for OS X users on the OCaml install website is straightforward:

brew install ocaml

brew install opam

If you’ve just run the above code and are on OS X, great news! That’s mildly wrong but pretty easy to fix. This works fine until you get to the tutorial which involves talking to the graphics library and start seeing Error: Unbound module Graphics. This is because of a xquartz dependency that doesn’t get installed by default.

You can go and upvote Shoe for sharing that by default the brew install is missing a dependency and you’ll want to run:

brew install Caskroom/cask/xquartz

brew [re]install ocaml --with-x11

You should also install UTop, which is kind of an awesome wrapper for the OCaml repl. It provides autocomplete, command history, etc, but the thing I am enjoying the most is that as you type a given word it maintains an alphabetized autocomplete list of potential completions at the bottom of the line. This makes for easy scanning and encourages accidentally learning of the existence of new functions. It shows everything available in the current namespace so accessible library and user defined functions also get shown.

Just run the following (promise this set isn’t slightly wrong) in the terminal:

opam install utop

eval `opam config env` # add this line to your .bash_profile

and now to get to the OCaml repl (which ocamels call TopLevel?) run the command `utop`.

UTop, suggesting things

Things are looking up. We got this snazzy REPL/TopLevel (there’re all sorts of configs for it too if that’s your jam), we’ve dodged a dependency issue, we’re good to go with the tutorial and actually write some OCaml!

Actually Writing Some OCaml!

Let’s define some values. And a function that multiplies things by 5.

utop # let foo = 5;;

- : int = 5 utop # let bar x = foo * x;;

val bar : int -> int = <fun> utop # bar 5;;

- : int = 25

If we redefine foo, the value of the original foo doesn’t change. This is in UTop, I am not sure how this behaves for compiled programs, it might error.

utop # let foo = 10;;

- : int = 10 utop # bar 5;;

- : int = 25

We can get real variables using refs.

utop # let r = ref 50;;

val r : int ref = {contents = 50} utop # let baz x = !r * x;;

val baz : int -> int = <fun> utop # baz 2;;

- : int = 100 utop # r := 25

- : unit = () utop # baz 2;;

- : int = 50 utop # let ref_arg_fn x = !z * !x;;

val ref_arg_fn : int ref -> int = <fun>

The `ref` assignment means that it’s a mutable variable and not an immutable value along with the flexibility and danger that comes with that. The `:=` operator is for reassigning ref values, and the `!` is for de-referencing refs.

Another interesting thing to note is that the type changes if one of the arguments is intended to be a reference instead of the value it references, and that additionally, that reference is expected to contain that specific type. If you look at `ref_arg_fn` you can see that the arg type is `int ref` instead of `int`.

Graphics!

So the code above has all been a colloquial paraphrase of the tutorial code. One thing I want to note before turning in for the night. OCaml’s tutorial goes on to show it’s module system with a very neat demonstration with OCaml Graphics. It seems very cool, I can draw things on the screen in only a couple lines. The only problem is when you follow the instructions and enter

open_graph " 640x480";;

you might get ‘Graphics.graphic_failure exception “Can not open display “ ”’. This might cause you some distress and waste several hours of your time while you try renaming env variables, attempt different arrangements of arguments, and modify your .bash_profile. After which point you may decide to resort to the debugger’s prayer, and solemnly reboot the machine. This may in fact work, and it did work for me. Try rebooting first if you run into the ‘Can not open Display “ “’ issue. I think it has something to do with the xquartz/brew thing mentioned earlier.

Victory

3 hours after “Can not display..”

3 hours and 1 minute after “Can not display…”

So now that everything seems to be operating sanely and all the toes I could manage to stub appear to be stubbed, it’s finally on to the fun part of learning the new language.