Unary Message Passing Systems
In working on the JS language engines, I've been thinking about currying in an object oriented language context. If you view a language as a set of unary message sends to the current object context that transforms the context, the system looks like:
O m -> O | O' | O2
That is to say applying m to O will produce any of:
- no effect
- transform the object's internal state
- produce a new object context
If you think of the object as a function that maps the message to a new object
O(m) -> O'
Then O' is itself a function which will map the next message:
O'(m') -> O''
Which is exactly how my current code works. There is a one object deep stack with additional contexts created for generated messages. Since nested contexts can always be expressed as a sequence of operations on a stack, the only real constraints are the sequencing of side effects. For example if generating the outer most object instantiates a database session that all nested contexts implicitly require we may not be able to defer initialization. Similarly, if an object requires a forward reference to a delegate for dynamic dispatch, we may have an initialization race condition if instantiating the delegate could trigger behavior of the object containing the forward reference. While nothing in our message passing idiom prevents us from working around these design flaws, it can be difficult to accommodate assumptions made aboutthe ordering of side effects in 3rd party code.
To make this more concrete, let's consider how Numbers can be made to perform arithmetic with only unary operations. Take the number 2:
2 + -> function(x)
2 + 3 -> (function(x))(3) -> 5
This is straight forward partial application, where the result of applying a message to a numerical object is a function object which will map the next message to an arithmetic value, namely 5 in this case. If you look at it from the standpoint of doing this in forth, + * - / mod and the like all generate new CFA calls to a constant operation. It is important to note that if we go down this route, we are generating a new little bit of functional code each step of the way.