Just a warning for newcomers who follow after me. I spent about four hours yesterday desperately trying to figure out a bug that turned out to be the fact that execution order is unspecified.
I know, all of you who have been using the language for more than eight and a half minutes knew this already, and it is indeed documented, but it’s an unexpected enough sort of thing to the naive that it’s probably worth mentioning, in any tutorial or book, just as soon as you start mentioning side effects, in nice bold letters, perhaps with a “don’t say we didn’t warn you if you forget about this!” attached.
Just in case someone coming after me is tearing their hair out and finds this via google:
If f and g have side effects,
f a :: g b
might not (indeed, probably will not!) end up executing f before g, and you need to do something like:
let x = f a in
let y = g b in
x :: y
To get f and g to execute in the order you are naively expecting.
Yeah, this is not my favourite thing about OCaml. Note that you don’t have to manually hoist every side effecting part of an expression: it is enough to use let to indicate which ones come first, like this:
The way is to avoid side-effects or capture them with the various techniques.
Undefined evaluation allows for optimisations that can happen with pure code. I see them as a good thing. For example in that list, both sides can be evaluated simultaneously and concatenated when ready, independently of what finishes first.
So in this case I was doing I/O, so order was important to me. And yes, a monadic approach would have made the ordering much more explicit. On the other hand, one of the nice things about OCaml is one isn’t required to go to pure functional solutions.