

OCaml: Objects - haifeng
https://haifengl.wordpress.com/2014/07/16/ocaml-objects/

======
kxyvr
What I never understood is why OCaml allows row polymorphism in objects, but
not in record types. For example, we can write:

    
    
      let bar x = x#info + 1
    

and OCaml will give a type:

    
    
      val bar : < info : int; .. > -> int = <fun>
    

which is precisely what we want since we can now define functions on any
object that has an info member. At the same time, we can't write

    
    
      let buz x = x.info + 1
    

because we receive the error

    
    
      Error: Unbound record field info
    

This is a big deal since the exposed members of objects must be methods in
OCaml. Certainly, we can declare values and mutable values, but these are not
exposed in the objects type. Specifically,

    
    
      # class foo = object val info = 1 end;;
      class foo : object val info : int end
      # let bar = new foo;;
      val bar : foo = <obj>
      # bar#info;;
      Error: This expression has type foo
             It has no method info
    

In order to get around this, we can change these values to methods (or add
getter methods that return these values). However, the problem with doing that
is then we can't make a new object with all of the same values, but with the
specified valued changed:

    
    
      # class foo = object method info = 1 end;;
      class foo : object method info : int end
      # let bar = new foo;;
      val bar : foo = <obj>
      # bar # info;;
      - : int = 1
      # let buz = bar with info = 2;;
      Error: Parse error: [str_item] or ";;" expected (in [top_phrase])
    

In other words, we don't have a good mechanism for creating a bunch of
immutable objects.

In other words, OCaml records allow immutable records, but they lack row
polymorphsim. OCaml classes allow row polymorphism, but disallow immutable
updates (immutable updates meaning create a new object with everything the
same, but one element different.)

Does anyone know why this is the case?

~~~
rwmj
I believe it's because #info (ie. method access) is kind of dynamic. The
string "info" is hashed and then the hash is looked up at runtime against the
class vtable. (For precise details, see 19.3.5 here:
[http://caml.inria.fr/pub/docs/manual-
ocaml/intfc.html](http://caml.inria.fr/pub/docs/manual-ocaml/intfc.html)) I'm
not clear under what circumstances this can be optimized to a direct call, and
there is also some kind of cache, so repeated method calls to the same method
are fast. This is the reason people who value performance over everything else
steer clear of using objects in OCaml.

Record fields are simply offsets in a struct, so the type must be fully known
when compiling the code. It would not be possible to compile a function that
could work on two different types of struct that both happened to have a .info
field.

~~~
kxyvr
Actually, that makes a lot of sense. Thanks for the insight.

------
tel
Total agreement!

OCaml's object system is wonderfully austere. It arises as a pretty natural
extension of the more restrained signature subtyping relation---and this helps
drive home, as this article also emphasizes, the vital distinction between
subclassing and subtyping. That alone means that you'll have a more well-
principled and reasonable object system than basically any other one I've ever
used.

In day-to-day OCaml, I often hear people suggest that one should avoid the
object system. The primary things it buys you are access to the row-typing
system and class/object constructor hierarchies. It however is a bit slower
due to the use of dynamic dispatch (instead of compiling vtables statically to
their use site) and can face some inference issues.

That said, row types are an incredibly useful type construct (often Haskellers
lament the fact that they're missing leading to the creation of things like
Ermine and Vinyl). Cautious use of the object system is very exciting!

------
evmar
This post is also a great demonstration as to why a programming language
cannot be evaluated as a feature checklist.

OCaml's object system is certainly awesome but in practice you'll find it is
unevenly used -- some never use it, while I'm sure there are others who use it
heavily. Because it behaves in a way that is not quite compatible with the
rest of the language it is inconvenient to mix APIs that use the two styles of
programming. Another comment here on HN links to a post that summarizes with
the rule of thumb of simply "don't use objects".

The lesson is that any given feature exists in an ecosystem of other features
and its utility is dictated by many things (impedance mismatch with the rest
of the language or even language cultural problems) other than the
specification itself.

~~~
rwmj
I have a slightly more nuanced point of view. I pretty much write OCaml code
for a living, and rarely use objects, but that's because they are rarely
useful (as a general concept, nothing to do with OCaml).

To give a concrete example of a program where I happened to use objects for
the first time in ages[1], most of the program works by defining a set of
types[2], and then using simple functions to work on those types. The program
is essentially: transform the input structure to another structure to another
structure. All the structures are publicly defined making it really easy to
understand the program and debug when things go wrong. The flow of execution
is simple and obvious, and the compiler picks up possible errors in that flow
because of the strong typing.

But there happened to be one place that I wanted the ability to hide data +
use implicit variant code alongside that data, and then I switched over to
using objects[3]. It's a narrow use case and I've written a lot of code
without ever needing that.

Of course in OOP languages you essentially have to use objects to get any work
done, and so people go crazy and it's impossible to follow the flow of
execution.

[1]
[https://github.com/libguestfs/libguestfs/tree/master/v2v](https://github.com/libguestfs/libguestfs/tree/master/v2v)

[2]
[https://github.com/libguestfs/libguestfs/blob/master/v2v/typ...](https://github.com/libguestfs/libguestfs/blob/master/v2v/types.mli)

[3]
[https://github.com/libguestfs/libguestfs/blob/master/v2v/typ...](https://github.com/libguestfs/libguestfs/blob/master/v2v/types.mli#L164-L193)

~~~
djur
I'm not a very experienced OCaml developer but after several iterations on a
simple game engine in OCaml I found that there were a few places I could
significantly reduce boilerplate by using objects. Entities in a game
frequently need to carry around their own internal state.

------
agumonkey
Older, hopefully still relevant, article about OCaml objects :
[http://roscidus.com/blog/blog/2013/09/28/ocaml-
objects/](http://roscidus.com/blog/blog/2013/09/28/ocaml-objects/) (from
0install author)

------
BrianEatWorld
I went in expecting to see a write up on Common Lisp's CLOS[1], because at a
recent Clojure Meetup, the speaker put forth the claim that CLOS is the most
powerful OO system out there. He didn't have time to validate the claim, but
it may be of interest to those who like this article.

[1] [http://cl-cookbook.sourceforge.net/clos-tutorial/index.html](http://cl-
cookbook.sourceforge.net/clos-tutorial/index.html)

~~~
theevilcellist
Was that the one in Austin last week?

Also, I highly recommend Doug Hoyte's Let Over Lambda[1] where he goes into
detail about a certain duality of closures and objects.

[1] [http://letoverlambda.com/](http://letoverlambda.com/)

~~~
wirrbel
SICP does the job of demonstrating the Closure-Object relationship just as
fine, without boring the reader with endless references to the superiority of
Lisp, as Let Over Lambda does.

~~~
hyperpape
From the blurb:

"Let Over Lambda is one of the most hardcore computer programming books out
there. Starting with the fundamentals, it describes the most advanced features
of the most advanced language: Common Lisp. Only the top percentile of
programmers use lisp and if you can understand this book you are in the top
percentile of lisp programmers. If you are looking for a dry coding manual
that re-hashes common-sense techniques in whatever langue du jour, this book
is not for you. This book is about pushing the boundaries of what we know
about programming. While this book teaches useful skills that can help solve
your programming problems today and now, it has also been designed to be
entertaining and inspiring. If you have ever wondered what lisp or even
programming itself is really about, this is the book you have been looking
for."

~~~
wirrbel
I should have known better when I ordered the book.

Hoyte's first intention, writing a 2nd Volume for Paul Grahams On Lisp, which
goes into detail about macros, is actually quite good. It just does not live
up to "Volume 1".

And about the 1 percentile and "only the best" talk: Lisp and Lisp Macros are
not really "magic". They are accessible to programmers like you and me and if
someone does not bother to write them it is not about lack of understanding,
but lack of time it takes to write them properly.

~~~
hyperpape
Interesting to hear. I don't have a particular opinion about the book, beyond
having heard some praise, but I do think that blurb is assinine.

------
aplusbi
OCaml objects are pretty neat, although I rarely ever end up using them.
Although I also rarely ever use OCaml for that matter.

One issue with the article - the author confuses duck typing and structural
typing. While they are similar, there are important differences. OCaml uses
structural typing (which enforces type at compile time) and not duck typing.

------
jsnell
To me the post is really not making the case at all that OCaml's object system
is "best", as suggested in the HN headline. Really the only comparison to any
other system is contrasting row polymorphism to duck typing. Like another user
I was actually expecting this to be about CLOS based on the title. It'd still
be a hard claim to make given some of the warts CLOS has, but at least it's a
claim that people will often genuinely make.

(This also seems to be the fourth time the same post was submitted by the same
user, with increasingly clickbaity headlines.)

~~~
dang
A small number of reposts is ok if an article hasn't had significant attention
yet (see the FAQ). I'd say this is about the limit, though.

You're right about the submitted headline ("Best object system is actually
from a functional language").

