As an ArgoUML contributor I'm going to blog my activities here, so that they may draw interest by other developers or help other developers when doing tasks similar to what I've done. AND(!) the grand vision that makes an Argonaut what he is, TO THRIVE IN THE BIG DANGEROUS WORLD, TAKING THE Argo TO A GOOD SHORE ;-))

Saturday, March 20, 2010

The Functional Object System idea

Functional languages and functional programming techniques are getting into the mainstream of software development these days. Clojure is an example of a recently created language (a Lisp dialect) that although not purely functional, applies the techniques and principles of functional programming very seriously and IMHO with success. Now, how do we combine this in a seamless way with object oriented programming? OOP has been up-to-now very dependent on the objects having mutable states in a destructive way. This isn't compatible with the functional data types which although having state, this is immutable, being the objects' data shared and construction only – and therefore reusable.

My idea is that we need a new object paradigm, which enables easy definition of immutable objects which have the same nature as the functional data types. I've seen this to some degree in a specific SISCOG library defined as an extension to CLOS and that enables an object state tree – much more advanced than the typical command pattern stack based undo/redo functionality you commonly see. It could be implemented in Java with aspect oriented programming (i.e., with AspectJ). Alas, this library suffers from its objective not being specifically of providing a Functional Object System (FOS) and by using the mutable Common Lisp standard types – once you get hold to one of its fields, you can wreck the state indirectly. It also relies on the common with wrapper macros to change from state to state, instead of assuming that all state changes shall be construction only and therefore dropping the use of wrapper macros.

So, what specific concepts must a FOS take to heart in order to work?

  • Differentiate between query operations and construction operations.
  • Construction operations always return new objects that shall have one or more of their fields with different values than the objects they clone.
  • There shall be ways to change the state of the application, pointing some reference to a new root node tree, but, these shall follow concurrency (and maybe distribution) aware protocols, such as the ones defines in Clojure. These aren't necessarily part of the FOS, but, the FOS must play well with these.
  • The FOS shall provide means for its objects to take advantage of non-FOS objects. E.g., a FOS for Clojure must provide a potentially largely inclusive way for impure mutable Java defined objects to be used with it, even if that means to take advantage of introspection on these objects' operations and expensive quasi-duplication of them without the benefit of reuse.

So, now that I had one more crazy idea thrown into the web, lets check prior art...

OCaml has objects and contains a basis operation called functional update. This provides the basis for maintaining that an object is data plus behavior, but, making it side effect free. The convenience it provides is very interesting, it is almost more terse than actually mutating the objects! Even so, you have the possibility to use an imperative style, but, it isn't the default and you must declare the methods that actually change with mutable.

In Clojure it is all about concurrency, so, you would have to guard against concurrent access to objects that are being mutated. So, there might be additional semantics involved, which weren't obvious in the small part of OCaml that I read.

2 comments:

Slobodan Blazeski said...

The problem is that the mutation is in the core of the OO style. Not a creation of a new objects but changing the state of the existing ones. I swear that I'm avoiding as much state in my work code (Java now and C# before), I declare everything I can const, static, final etc but since pretty much everything else relies on mutation I must play their game. So this marriage seems very unlikely to succeed. OO is good for visual representation of controls but for everything else it fails apart immediately.

euluis said...

Yes, you're right Slobodan, but, you and I use java.lang.String and the primitive types which are immutable in OO code without problem...

Maybe its just a crazy idea, but, I would still like to explore it a bit. Currently I'm considering some words by Stuart Halloway in a Clojure presentation about identity...

Basically the state should be mutable, but, only for a different point in time and/or location, like in the real world when I change, it is in a different point in time. Distribution could and should be handled the same way. This is in line with something I saw about eventual consistency.

For instance, the Slobodan I'm addressing now in my comment should be a bit different from the Slobodan that wrote the comment. If I want to call you by phone I should call the Slobodan of now:

(phone-call :who (:slobodan-blazeski persons :time (now)))

This means I could have mutable state, but, I wouldn't have inconsistent objects since each object is consistent for a point in time and location.

PS: this thing of time and location is an idea I had after having written the post. Maybe I'll write a follow-up.

Thanks for showing up and commenting.

Reader Shared items

Followers