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
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.