Begin forwarded message:
Date: January 23, 2006 11:37:14 AM PST
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:
Begin forwarded message:
Date: January 23, 2006 12:12:19 PM PST
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,
--
Begin forwarded message:
Date: January 23, 2006 12:21:34 PM PST
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
Begin forwarded message:
Date: January 23, 2006 12:23:13 PM PST
Subject: Re: [Caml-list] (no subject)
Hello,
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
--
5996 CC46 4612 9CA4 3562 D7AC 6C67 9E96 A3AD 7A2A
Begin forwarded message:
Date: January 23, 2006 12:24:19 PM PST
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:
Date: January 23, 2006 1:39:29 PM PST
Subject: Re: [Caml-list] (no subject)
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
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:
Date: January 23, 2006 10:44:44 PM PST
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>
Begin forwarded message:
Date: January 24, 2006 2:35:15 AM PST
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.
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:
Date: January 24, 2006 4:40:37 PM PST
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:
Date: February 10, 2006 5:55:37 AM PST
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