thiagowfx's avatar

¬ just serendipity 🍀 (not just serendipity)

OCaml starters

• 904 words • 5 min • updated

⚠️ This post is over one year old. It may no longer be up to date or relevant. Opinions may have changed.

You should read this post first.

Last week or so I thought I would start to learn Perl or Lua, but I discovered OCaml…and then my focus instantly shifted into it. I’m not really sure what I’ll do about the language, but for now I’m studying it a little bit, so I’ll post here a few notes about it.

Note: this post is likely to be updated as I progress through the language; alternatively, a new post might be created, or I can abandon this thing altogether (yeah, this happens).

So #

  • To get an interpreter: ocaml

    • Now enter valid OCaml expressions, and finish them with ;;
    • You can enter more than one expression at a time, e.g.
    ocaml
    let x = 1
    let y = 2
    ;;
    • Equivalently, you can write a script.ml file and enter these same commands, then enter into the interpreter and type:

      ocaml
      #use "script.ml";;
  • Alternatively, you can compile this script with ocamlc. This will create three files: an executable (a.out by default), a.cmi (interface) and a.cmo (object file).

  • To run an OCaml executable, use ocamlrun.

  • Up to here, this is very similar to haskell: ghc, ghci, and runhaskell.

  • Pattern matching is very easy overall (as with haskell)

  • ocaml
    let isvowel c =
        match c with
            'a' | 'e' | 'i' | 'o' | 'u' -> true
            | _ -> false;;
  • However, I find P.M. (pattern matching) more explicit with OCaml. Haskell uses function overloading to implement pattern matching (at least in the syntax level), while OCaml uses a switch-like statement to do that. Well, actually haskell desugars function overloading to a ‘case’ expression behind the scenes, which is very similar to OCaml’s match, but hey…it is just slightly easier to read the OCaml syntax.

  • You can use _ to match anything.

  • You can also use _ to ignore what is not relevant to you in a match, e.g. when matching tuples:

  • ocaml
    let fst (x, _) = x;;
    let snd (_, y) = y;;
  • You can match character ranges, e.g. ‘A’..‘Z’.

  • Two bindings are available: let and let rec. The last one is used to define recursive functions, and they are fundamentally the same; the difference lies in scoping rules (e.g., when using let … in). Example of let rec:

  • ocaml
    let rec factorial n =
        if (n < 0) then failwith "negative factorial!"
        else if (n = 0) then 1
        else n * factorial (n-1);;
  • OCaml from the very beginning is a super nice intro book to the language. I gave it a 5/5 on Goodreads.

  • Examples from the book: in this user repository.

  • Logical operators are not exactly what you expect regarding equality: = and <>. Yeah, not ==. Annoying, huh?

  • true and false are written in lowercase. Different from python, equal to ruby. Why are programming languages so different? At least, if you write it wrong, you are prompted with a nice message:

  • text
    Error: Unbound constructor True
    Hint: Did you mean true?
  • Speaking of messages, error messages from OCaml are veeeeeery good. It looks like its creators know how to actually communicate with other humans (gcc, this is a subtle sarcasm directed to you!). Want to see an example? I’ll give you one about a warning:

  • ocaml
    let f l =
        match l with
        [] -> True;;
    
    (* Response: (yeah, this is a comment!)
    
    Warning 8: this pattern matching is not exhaustive.
    Here is an example of a value that is not matched:
    _::_
    val f : 'a list -> bool = <fun>
    
    *)
  • Naming convention when deconstructing lists: h::t. This means head and tail. In haskell, we usually use x:xs.

  • Oh yeah, haskell is : while OCaml is :: while in the lisp family of languages this is cons.

  • And the append/concatenate operator is @. In haskell it is ++, in python it is +.

  • Yeah, I keep comparing OCaml with other languages because I find it easier to understand it this way.

  • A list in OCaml is a single linked list behind the scenes. So the :: operator only acts on one side of the list…you’re screwed if you want the other one – alternatively, revert the list or use a better data structure.

  • Speaking about lists….[1;2;3;4] not [1,2,3,4]. The last style is from Python / Haskell / Ruby.

  • Package manager? Yeah! opam. This should be analogous to RubyGems and Haskell’s Cabal or node’s npm. *opam install, opam remove, opam search…*I keep writing it opan, for some reason.

  • I love this feature: every function in OCaml has only one parameter. Native currying (aka partial application) FTW! Like haskell.

  • The compiler is pretty smart about inferring types, but annotations can be made too:

  • ocaml
    let sum10 (x:int):int = x + 10;;
  • Anonymous functions:

  • ocaml
    fun x -> 2 * x
    
    (* example of use with map: *)
    map (fun x -> 2 * x) [1; 2; 3] (* yields [2; 4; 6] *)
  • Just comparing with haskell, which is slightly smaller:

haskell
map (\x -> 2 * x) [1..3]

-- or, better yet
map (* 2) [1..3]
  • Actually, it is possible to use something such as (+) or (<=) in OCaml. But…not (*). This is confused with a comment. Maybe there is a way of escaping this. Edit: yeah, we just have to insert spaces: ( * ).

I guess I’m stopping here for now. This includes up to chapter 6 of the aforementioned book, plus a few random sources on the web. ∎


ESC