A few weeks ago I sent email to ocaml mailing list asking about experiences with the "o" part of "ocaml".  I include below the responses that I received.  

There are a lot of different opinions! The summary seems to be that people use objects
 1. to wrap oo libraries from other languages
 2. to wrap long-lived imperative abstractions behind a clean interface
 3. when dynamic code selection is important

There is some difference of opinion on how easy the features are to use: some say they are easy, others too difficult to bother with.  

The most difficult element seems to be with type inference being too generous, making programs more polymorphic than intended and delaying error messages.  The workaround is to add type annotations to limit the polymorphism of the code. 

Kathleen


Begin forwarded message:

From: Kathleen Fisher <kfisher@research.att.com>
Date: January 23, 2006 11:37:14 AM PST
To: caml-list@yquem.inria.fr
Cc: John Reppy <jhr@cs.uchicago.edu>
Subject: [Caml-list] (no subject)

As part of our work on Moby, John Reppy and I are collecting
experiences people have had using the object-oriented features of
Ocaml, as it has been available long enough for people to use it "for
real."

We are interested in understanding what people use the object-oriented features for.  What works really well?  What doesn't work so smoothly?  How do you decide when to use the object-oriented features?  Do you have other observations you'd like to share?

I'm happy to summarize responses sent directly to me for the list.

Thanks in advance!
Kathleen Fisher





_______________________________________________
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs
Begin forwarded message:

From: Anil Madhavapeddy <avsm2@cam.ac.uk>
Date: January 23, 2006 12:12:19 PM PST
To: Kathleen Fisher <kfisher@research.att.com>
Subject: Re: [Caml-list] (no subject)

[off-list]

Kathleen,

I use the OO features as part of a data description language I've
developed called MPL, for writing high-performance OCaml network
servers (not yet released).  The language is similar to PacketTypes,
but outputs OCaml code instead of C code.

The generated OCaml code has a unique OCaml object type for each
packet type (separated in the namespace by modules).  Each object
contains the functions to marshal and prettyprint that packet and
accessor functions to retrieve and set individual fields.  Unmarshal
functions convert network traffic into variant data types, so that
ML pattern matching can be used on received data.

I've developed quite a few apps with this so far (SSH, DNS, DHCP,
IPv4 router, others have done Plan9FS and are implementing a TCP
stack) in pure OCaml, and its been quite effective.  Packet parsing
code in OCaml which generates minimal garbage is pretty ugly/imperative,
and its nice to hide it away inside the object interface.

The most painful thing about objects and polymorphic variants in
OCaml are the error messages if the objects aren't annotated properly;
but this really isn't a problem if the objects are all _generated_,
annotated with types and stuck in a library.  Objects are much more
pleasant to actually use than a combination of the module system
and records, since they dont require prefixing the module name to
access fields inside records (a real pain in previous versions of
my network servers that didnt use objects).

I've read your work on PADS with interest; it's really useful for
interfacing with configuration files and log files for the OCaml
servers we've developed, so I was quite keen to look into writing
an OCaml version of it instead of C.  But one step at a time;
finishing the PhD dissertation first :-)

best regards,

-- 
Anil Madhavapeddy                                 http://anil.recoil.org
University of Cambridge                          http://www.cl.cam.ac.uk


Begin forwarded message:

From: Martin Jambon <martin_jambon@emailuser.net>
Date: January 23, 2006 12:21:34 PM PST
To: Kathleen Fisher <kfisher@research.att.com>
Subject: Re: [Caml-list] (no subject)

Hi Kathleen,

In my experience, objects in OCaml are mostly appropriate to represent complex mutable data that does not have to be combined with other objects of the same kind and when there is no problem of efficiency (since method calls are not as fast as record field access).

Examples include:

- representing a mechanical object which contains position, velocity,
forces, masses, etc. Forces, translations, speed limits, and so on can be changed at each timestep, and all fields become updated according to specific rules. The high number of internal fields and the long life of such an object are the factor that decided me to use objects in this situation. In this case, inheritance was also used to derive subclasses of objects, but I could have done without it. In general, the use of sum types to represent variants of a given core type is much easier than using class inheritance in my opinion.
- I/O objects: creating the object is equivalent to opening the resource for reading, writing or both. Again, this is an object which has a long life with a highly mutable internal state. See http://ocaml-programming.de/rec/IO-Classes.html which is proposed standard for I/O classes.

As for polymorphic variants, my feeling is that developing libraries which provide an object-oriented interface is more difficult, but from the user's point of view it is often easier than using a library which is based only on the core OCaml language.


Martin
Martin Jambon, PhD
http://martin.jambon.free.fr

Visit http://wikiomics.org, the Bioinformatics Howto Wiki
Begin forwarded message:

From: David MENTRE <dmentre@linux-france.org>
Date: January 23, 2006 12:23:13 PM PST
To: Kathleen Fisher <kfisher@research.att.com>
Subject: Re: [Caml-list] (no subject)

Hello,

Kathleen Fisher <kfisher@research.att.com> writes:

As part of our work on Moby, John Reppy and I are collecting
experiences people have had using the object-oriented features of
Ocaml, as it has been available long enough for people to use it "for
real."

I'm using Lablgtk for the client of the demexp software.

We are interested in understanding what people use the object-
oriented features for.

To use a OO toolkit, Lablgtk.

 What works really well?

Objects are typed, so no bad surprises *if* it compiles. Other than
that, I can't really say, sorry.

 What doesn't work so smoothly?

- combination of OCaml objects with a functional programming style: in
  case of typing error the error messages are too far from the original
  cause and too verbose[1].

- syntax and subtyping: certain mandatory casting are like "black magic"
  to me. I've just copy/pasted from Lablgtk examples. But maybe I
  haven't investigated enough the type system.

- complexity. Compared to SmallTalk or even Python, OCaml objects are
  quite complicated (to say the least). 

How do you decide when to use the object-oriented  features?

- because Lablgtk uses it, so I'm forced to use it.

- as an experiment, to try an object oriented application in
  OCaml. Until now, I've only been convinced that the OCaml objects are
  not for the casual programmer.


Do you have other observations you'd like to share?

- documentation, documentation and documentation, with
  *examples*. Current documentation is probably sufficient but far too
  light in my humble opinion. Especially on those strange corners,
  e.g. in "class [[> Gtk.widget ]] widget_impl : ([> Gtk.widget ] as 'a)
  Gtk.obj -> object .. end"[2], why "as 'a"? 


Feel free to ask for more information if I'm not clear enough.

Best wishes,
david


Footnotes: 
[1]  This is the first time I had one page long error message in OCaml,
     without having any idea of why.

[2]  liblablgtk2-ocaml-doc/html/GObj.html

-- 
pub  1024D/A3AD7A2A 2004-10-03 David MENTRE <dmentre@linux-france.org>
 5996 CC46 4612 9CA4 3562  D7AC 6C67 9E96 A3AD 7A2A

Begin forwarded message:

From: Diego Olivier Fernandez Pons <Diego.FERNANDEZ_PONS@etu.upmc.fr>
Date: January 23, 2006 12:24:19 PM PST
To: Kathleen Fisher <kfisher@research.att.com>
Subject: Use of objects in Caml

    Bonjour,

We are interested in understanding what people use the object- oriented
features for.  What works really well?  What doesn't work so smoothly?
How do you decide when to use the object-oriented features?  Do you have
other observations you'd like to share?

Long time ago I wrote a data structure library containing functorial,
polymorphic and object versions of each data structure/algorithm. It was
intented for combinatorial optimization problems.

I never used the object layer.

I had a few request of people asking how to do this or that. They never
needed the object layer.

Dynamically changing the underlying data structure representation which
was purpose of the object layer remained a dream in all the applications I
developped with it : in a typical program (including performance
intensive) there are a ton of improvements that lead to more significant
wins.

- By the way, Pascal Brisset and Nicolas Barnier who wrote the constraint
programming system FaCiLe also removed all the objects they were using -

What doesn't work so smoothly ?

Bad integration with Caml functional core, both semantic and syntactic.
Too much redundancy without clear benefits. In some cases variants are as
good. In others the functor/module system is enough.

How do you decide when to use the object-oriented features?

I just stopped using objects.


        Diego Olivier Fernandez Pons

Begin forwarded message:

From: David Baelde <david.baelde@gmail.com>
Date: January 23, 2006 1:39:29 PM PST
To: Kathleen Fisher <kfisher@research.att.com>
Subject: Re: [Caml-list] (no subject)
Reply-To: david.baelde@ens-lyon.org

Hi,

I've been coding in OCaml for a long time, and I know many people
coding in OCaml, but I think I'm one of the few to have used objects
-- and to like it. That's why I felt I should answer. However I don't
have so much to say :p

I use OCaml for hobby projects and more usual academic stuff. I often
end up with objects on hobby projects, more "real-life" applications,
like audio processing software or text editors. My biggest project is
liquidsoap (http://savonet.sf.net) where I decided from the beginning
to use objects. There, abstract classes, (multiple) inheritance,
overriding, private declarations, are used a lot and are very helpful.
I'm not a OO guru, neither an OCaml OO guru, so I guess I don't use
many advanced features here.. in particular I rarely need to have
polymorphic classes.

I think the major reason for choosing objects is abstract classes,
inheritance and structural subtyping. It makes it natural to define
step by step some values which fit in some role. Again, I'm no guru
and haven't thought to this such a lot, but I believe that the
prototype-based choice in OCaml instead of class-based has something
to do with this ease. At least, I think it makes things simple and
easy to understand.

In general, I find that using objects in OCaml is very easy:
lightweight syntax, clear semantics and powerful constructs. I don't
have much too complain about.

Cheers,

David

Begin forwarded message:

From: skaller <skaller@users.sourceforge.net>
Date: January 23, 2006 10:44:44 PM PST
To: Kathleen Fisher <kfisher@research.att.com>
Cc: caml-list@yquem.inria.fr, John Reppy <jhr@cs.uchicago.edu>
Subject: Re: [Caml-list] (no subject)

On Mon, 2006-01-23 at 11:37 -0800, Kathleen Fisher wrote:
As part of our work on Moby, John Reppy and I are collecting
experiences people have had using the object-oriented features of
Ocaml, as it has been available long enough for people to use it "for
real."

We are interested in understanding what people use the object- 
oriented features for.  What works really well?  What doesn't work so  
smoothly?  How do you decide when to use the object-oriented  
features?  Do you have other observations you'd like to share?

OO features provide dynamic binding, which is more powerful
than polymorphism provided by any other feature other than
higher order polymorphism (which doesn't work properly in Ocaml).

However, the utility is heavily constrained by the variance
requirements.

The effect is that OO is often the best solution for
sources and sinks, and cannot be used for most relationships
(since they're usually covariant).

Thus, I am using Ocaml OO as sources and
for relationships where one type is invariant. In particular,
I am using it in the lexer phase of my compiler, with classes
to handle and factorise the state of the preprocessor/lexer,
parameterising Ocamllex action code.

Secondly, it is used to manage the inputs supplied to the
Ocamlyacc parser mainly to feed a stream of tokens to it.

In both cases the type of a token is invariant, and so
amenable to an OO solution. In both cases the technology
being leveraged -- Ocamllex and Ocamlyacc -- forces me
to control invert my logic and program reactively instead
of actively -- user actions of both tools are callbacks
driven by tool generated logic which provide no or very
limited ability to interact actively.

These uses are not intended to provide any abstraction,
they're just a convenient way to package up the functionality
and pass it around as a single value.

My back end would also benefit from use of classes.
The output data type involved -- strings -- is invariant.
Classes would provide abstraction which may assist in
making the code generator pluggable: at present it can
only generate ISO C++, it would be useful to generate C,
C--, Ocaml, or some other languages too.

This is not done at the moment, because using classes
requires knowing in advance what your abstractions are:
classes break badly with design changes. Algebraic data
structures are more flexible, adapt more easily, but it
is harder to reason about correctness when operating
directly on low level representations.

In fact, in the lexer classes, the enforced abstraction
(variables can't be accessed, you have to write get/set
methods) is actually a pain. As the system developed
I've had to add more variables and get/set methods ..
and declare separately the types in *.mli files ..
because much of the time I'm *really* working directly
with the representation. Refactoring would be a nightmare ;(

In another project I used classes much more heavily.
That project (Vyper) was an Ocaml program which implemented
the Python programming language. This was not only convenient
to model the Python objects as classes, it was also useful for
constructing lookup scopes, with methods representing the various
lookup rules.

There I used abstraction heavily, as a way of separating my
Ocaml implementation from the semantics, and this was tenable
because the semantics were well specified (by the Python language),
which itself is object based.

One final comment: classes would be MUCH more useful if, as
in C++, one had dynamically loadable code. In that case
algorithms can work with class types instantiated at run time,
the dynamic binding is fundamental, and the enforced abstraction
vital. I exploit this heavily in Felix, which generates shared
libraries which are dynamically loaded by a driver program,
which runs the code using C++ abstract base methods.

In Ocaml you have to link all the instances in anyhow..
so the dynamic binding isn't nearly as useful. For Vyper this
was one of the major factors killing the project: there
was a need to model all the C extension to Python -- and there
are a LOT of them -- the same way Python does: by dynamic loading.
The Ocaml emulation had to statically link every extension,
which apart from being a pain, introduces the possibility that
the intended bindings are not fully abstracted.

-- 
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net

Begin forwarded message:

From: Gilles FALCON <gilles.falcon@francetelecom.com>
Date: January 24, 2006 2:35:15 AM PST
To: Kathleen Fisher <kfisher@research.att.com>
Cc: John Reppy <jhr@cs.uchicago.edu>
Subject: Re: [Caml-list] (no subject)

For my part i use object when it is easier than functionnal programming.
I like in the functionnal programming the strong typing.

The Narbel's book (in french sorry) http://www.amazon.fr/exec/obidos/ASIN/271174843X/403-9058959-5653236
explain the different programming style, the advantage and inconvenient.

Of course if it is not the look and feel of a lambda programmer, he's book is pleasant to read. It is also a book is very close to your subjet and without too much theory.

Hope this help

Begin forwarded message:

From: brogoff <brogoff@speakeasy.net>
Date: January 24, 2006 4:40:37 PM PST
To: Kathleen Fisher <kfisher@research.att.com>
Cc: John Reppy <jhr@cs.uchicago.edu>
Subject: Re: [Caml-list] (no subject)

Hi,
    I use the OO features of OCaml mostly to get around annoying
restrictions of the record system. That means I avoid late binding and
open recursion, but I use classes as polymorphic records (minus
pattern matching). If OCaml had a sufficiently powerful record system,
and a mixin module system which would allow programming by extension, I'd
be fine if there were no classes, or direct support for open recursion.

    In the cases where I thought I could make use of true OO (late binding and
open recursion) I would have wanted multimethods anyways, and as I find the
simulation with visitor classes too complicated compared to just using
algebraic data types and explicit dispatch, I designed without OO.

    OCaml's OO is very powerful compared to many other OO languages, but
it doesn't fit with the ML way, and until very recently (with private row
types) the interaction with the module system was difficult. While I
was initially enthusiastic, I've program mostly without it now. More
polymorphism for records is what I'd like to see in the next ML.


-- Brian


Begin forwarded message:

From: Philippe Narbel <narbel@labri.fr>
Date: February 10, 2006 5:55:37 AM PST
To: Kathleen Fisher <kfisher@research.att.com>
Subject: Re: [Caml-list] (no subject)



We are interested in understanding what people use the object-oriented features for.  What works really well?  What doesn't work so smoothly?  How do you decide when to use the object-oriented features?  Do you have other observations you'd like to share?



Hello Kathleen,

I recently run through your caml-list message, and here
are shortly some general points about your questions...

There are at least two main practical needs which make
me to use the object system in place of the module
system in ocaml:

  - dynamical choice of code (this is what is mostly
    missing in the ocaml module system -- even if local
    modules mixed with imperative features make possible
    to somewhat overcome this, but in an awkward way...).

  - quite easy application of inclusion polymorphism
    with of sophisticated first class values (modules
    or ``polymorphic variants'' do not give the same
    comfort as objects).
    Also, inheritance can be combined with dynamic
    binding, so that method redefinitions really work
    (modules just allow for plain redefinitions).

    Of course, mutual recursive relationships are also
    possible for classes in a natural way (recursive
    modules in ocaml are not bad, but I never felt the
    need to use them: it seems that they mostly happen
    when modules are defined at a too fine grain).

However,

  - type abstraction means are missing in the ocaml
    object system (type definitions -- e.g. in Scala --
    are not possible in classes and objects, but also
    nested-inner classes are not available). Thus, a
    usual technique is to embed classes into modules/
    functors (a technique which works quite well, but
    can become cumbersome).

On the other hand,

  - A very good point to the ocaml object system is the
    ``open object types'' which make type inference
    fully operational on any program where method
    invocations occur. As a result, it is very easy to
    mix styles : classes are not a definitive modeling
    choice. There are just a powerful construction of
    new types, and the module system may remain mostly
    in charge.


I'll be quite interested in your summary about these
questions (and by the way, in new versions of Moby...)

Yours,
Ph. Narbel