Late-binding with Erlang

Upon browsing the source to the excellent MochiWeb, I came across a call to a function that, when I looked, wasn’t defined anywhere. This, it turns out, was a clue: Erlang has undocumented syntactic support for late-bound method dispatch, i.e. lightweight object-oriented programming!

The following example, myclass.erl, is a parameterized module, a feature that arrived undocumented in a recent Erlang release. Parameterized modules are explored on the ‘net here and here. (The latter link is to a presentation that also covers an even more experimental module-based inheritance mechanism.)

“Instances” of the “class” called myclass can be created with myclass:new(A, B) (which is automatically provided by the compiler, and does not appear in the source code), where A and B become values for the variables Instvar1 and Instvar2, which are implicitly scoped across the entirety of the myclass module body, available to all functions defined within it.

The result of a call to a new method is a simple tuple, much like a record, with the module name in the first position, and the instance variable values in order following it.

While this looks really similar to OO dispatch in other languages, it’s actually an extension to Erlang’s regular function call syntax, and works with other variations on that syntax, too:

4> {myclass,123,234}:getInstvar1().
123

The objects that this system provides are pure-functional objects, which is unusual: many object-oriented languages don’t clearly separate the two orthogonal features of late-binding and mutable state. A well-designed language should let you use one without the other, just as Erlang does here: in Erlang, using parameterized modules for method dispatch doesn’t change the way the usual mechanisms for managing mutable state are used. “Instance variables” of parameterized modules are always immutable, and regular state-threading has to be used to get the effects of mutable state.

I’d like to see this feature promoted to first-class, documented, supported status, and I’d also very much like to see it used to structure the standard library. Unfortunately, it’s not yet very well integrated with existing modules like gb_sets, ordsets and sets. For example, here’s what happens when you try it with a simple lists call:

Not exactly what we were after. (Although it does give brittle insight into the current internals of the rewrites the system performs: a {foo, ...}:bar(zot) call is translated into foo:bar(zot, {foo, ...}) – that is, the this parameter is placed last in the argument lists.)

2 Comments

all braindamaged fans of OOP dont know (and even never dont search for) drawbacks of inheritance. look, pals… inheritance _deliberately_ breaks modularity. and so all oop code will be more complicated than needed and have maintenance problems, comparing normal functional code. remember that erlang has hot code update? sum hot code update with inheritance and you get all luxury of fragile-base-class problems in your code. if you have functional programming language with modules than you _never_ need old stinky unsafe and useless OOP. inheritance is just ugly kludge for old procedural dog who cant learn new tricks. never FP languages have safe and more powerful features to use. use it. and _always_ think about possible problems with used features. think before that problems occure. dont use feature just because it “trendy”. why people used oop? simple. code will be bulky (more LOC), code have complex internal interdependencies. so more money for programmer – more money for writing plus more money for support. and support require calling original author – because only they know all used tricks. understand? oop produces worse code but worse code means more money for programmer…