Showing posts with label diesel. Show all posts
Showing posts with label diesel. Show all posts

Wednesday, May 19, 2010

Revisiting Multimethod Dispatch

I've been bitten two times by CLOS' multimethods, so badly that I became totally anti-MMD. The problem is that in CLOS, modifications to your class hierarchy can have unpredictable and unintuitive effects as to what method gets called.

The problem is neatly described in the Diesel specification (page 33), by Craig Chambers (now at Google, like his PhD student, Jeff Dean):
Multiple dispatching introduces a ... potential ambiguity even in the absence of multiple inheritance, since two methods with differing argument specializers could both be applicable but neither be uniformly more specific than the other. Consequently, the key distinguishing characteristic of method lookup in a language with multiple inheritance and/or multiple dispatching is how exactly this ambiguity problem is resolved.

Some languages resolve all ambiguities automatically. For example, Flavors [Moon 86] linearizes the class hierarchy, producing a total ordering on classes, derived from each class’ local left-to-right ordering of superclasses, that can be searched without ambiguity just as in the single inheritance case. However, linearization can produce unexpected method lookup results, especially if the program contains errors [Snyder 86]. CommonLoops [Bobrow et al. 86] and CLOS extend this linearization approach to multi-methods, totally ordering multi-methods by prioritizing argument position, with earlier argument positions completely dominating later argument positions. Again, this removes the possibility of run-time ambiguities, at the cost of automatically resolving ambiguities that may be the result of programming errors.
So, the problem with CLOS is that it linearizes classes, and then also makes the function arguments to the left more important than those to the right.

Diesel's solution, which I don't understand fully yet, instead warns programmers of such ambiguities, and requires them to be resolved manually. Which sounds good, and may be a reason to revisit MMD for me.

Multimethods do rock, after all.

Type systems for dynamic languages

In the past days I've studied type systems for OOP, with an eye towards making them work in a Lisp.

Cecil and its successor Diesel already do this. There, type systems are purely optional:
Diesel supports the view that static type checking is a useful tool for programmers willing to add extra annotations to their programs, but that all static efficiently-decidable checking techniques are ultimately limited in power, and programmers should not be constrained by the inherent limitations of static type checking. ... Accordingly, error reports do not prevent the user from executing the suspect code; users are free to ignore any type checking errors reported by the system, relying instead of dynamic type checks. Static type checking is a useful tool, not a complete solution
I think that's a good spirit.

Both languages support F-bounded polymorphism, which is a fancy way of saying that you allow recursive types, like T extends Foo<T>. With this simple mechanism, the expression problem can be typed, and that's something.

(Scala and O'Caml extend upon this, each in their own way (here and here), but I think they're much too complicated for what I have in mind.)