Wednesday, January 11, 2012

Where my Clojure plays with protocols, multimethods and the SICP

Hello again.

I wanted to share today the implementation of one of my exploration of the SICP book, and get your feedback on the solution I came with.

While reading the book, I take the time to challenge both the exercises and code samples in Scheme - although I do regret not knowing it very well - and in Clojure. Somehow trying to reproduce each line of code in both languages can explain why it takes so much time :).

Part two of the bookis dedicated to the exploration of data abstraction and more specifically, section 2.4 leads us slowly to a data directed programming example. Starting from the canonical example of operations on complex numbers Abelson and Sussman, creates a layered complex-arithmetic system, starting at the bottom from primitive list structures, implementing complex numbers, up to program functions that use selector and constructor methods to manipulate complex numbers.

The top higher order operations are not supposed to be aware of the lower details of the implementation as we should use as many representations of complex numbers as we would like to, in the bottom layer.

Complex numbers can be represented by pairs describing rectangular or polar coordinate. Each of these representation suits more to specific operations. Adding two complex numbers is easier using a rectangular representation, while polar representation seems more adapted to multiplication for example. At any step we should be able to create new complex number instances from polar or rectangular data, which we can express as:

(make-from-real-imag 1 1)

(make-from-mag-ang 1 1)

In the first line we create a complex number for rectangular coordinates.The idoms real and imag respectively stand for real (x) and imaginay (y) components

In line two we create a complex number for polar coordinates. mag and ang respectively stand for magnitude(r) and angle (theta) components

At any step we should be able to select (x,y) components in rectangular representation and (r, theta) components in polar representation. What we wish to express is something like the following:

(real-part z1)
(imag-part z1)
(magnitude z1)
(angle z1)

All these constructors n' selectors should totally be unaware of the underlying representations.

But in addition, to conform to the SICP state of mind, the previous make-from-real-imag and make-from-mag-ang constructors should be adapted in order to choose the most suitable implementation. There, serious things begin.

In order to both explore SICP book while playing with Clojure idioms, I voluntarily chose to use protocols. In a certain way, like Abelson and Sussman (see section 2.4.1), I do not want my higher order operations to depend on specific implementations because there can be many of them, but I want my implementations to be contracted by my higher order module operations.

What I am expecting looks like a basic Inversion Of Control (IOC is a much higher concept than dependency injection, so check you do not confuse both ideas). Quoting Michael Fogus and Chris Houser's Joy Of Clojure: "protocols are set of function signatures, each with at least one parameter, that are given a collective name.

To digg a little deeper into protocols, check also Stuart Halloway and Aaron Bedra's book Programming Clojure and Stuart Halloway presentation over here.

To be perfectly honest I am not at ease with protocols as they do remind me to much of OOP in a Functional Programming context. That is debatable I think.
Both sets of constructors and selectors functions are perfect candidates for protocols.

that would make use of the make-from-real-imag and the make-from-mag-ang functions , I would like to be able to choose a suitable data representation on each .

Wait a minute, I wanted to invert the control, so naturally at the time of defining both the functions, in the same module as the protocols, I have no idea about which representation could be used. In order to get out of this trap enter multi-methods. The trick I used is not - I think - so different from Abelson and Sussman data directed programming.

Their proposal aims to update or get data in a two dimension table, one axis being the "type" of the representation and the other axis being a symbol defining the operation expected.

So each table cell hosts a reference towards the function, matching both a type and its operation. Implementing the protocols provides me with a dispatch on type. All I need is to identify my functions. Each function can be a multi-method declaration in the same module as the complex numbers protocols definition:

where in white color, rectangular-datum and polar-datum reference instances of the ComplexConstructor protocol, each of one being respectively invoked thruough the def-methodsmake-from-real-imag and make-from-mag-ang.

The dispatch functions used in the sicp.complex module being very simple our binding remains too very simple. We could maybe try to experiment on and make evolve the dispatching function to extend the power and flexibility of the binding in the sicp.test.complex-spec module.

Tests green.

So we have been able to define protocols, then we used elements from that protocols from higher order function and multi-methods, imposing our control to upcoming implementations, and finally we have been able to bind our higher order functions to the expected implementations. No that bad for a simple morning. Do not hesitate to come back with comments.