Originally posted by Pavel Kubal:
Now it makes sense
For a moment, consider the question - What exactly makes sense about copying array elements here and there? Let's look at an array.
An array is a construct that exposes a contract containing three operations. These operations are symbiotic - they cannot be separated. You can define these operations as:
1. E get(int) signals NoSuchIndex
2. void set(E, int) signals NoSuchIndex
3. int getLength
You can formally express the requirement of each operation, but paraphrasing is easier in communication.
The getLength operation is monadic - it forever returns the same value.
The set operation exists to have an observbable side effect on the get operation. In other words, there is a unidirectional relationship from the set operation and the get operation - the set operation has no legitimate existence without the get operation. The get operation may exist in isolation - it is not monadic. The get or set operation may signal to the client the inability to perform the requested operation - the signal name is NoSuchIndex. This signal isused in the event that the client exceeds the permitted bounds (which can be found through the getLength) operation.
There is nothing (not quite true - see below) more to an array contract. How do you produce a different contract implementation with its own identity? Simply, how do you copy an array? You *must* copy elements since arrays are bound by a certain model of representation - this is an abstraction leak that is intrinsic to arrays. In fact, if arrays were nothing more than the above contract, you could implement a "unique contract implementation identity copy" without ever copying elements. Performance bigotry aside, the biggest benefit is that you have met your requirements with greater accuracy by eliminating excess - clients never know, or care, about how you have met their requirement (remember, this was not to copy an array, but to obtain a unique contract implementation identity representing the same "state" of some other contract).
This is exactly the premise that is used for net.tmorris.adt.sequence.Sequence[1] and since the type is immutable (all operations monadic), there is never a legitimate use case for acknowledging contract implementation identity. You can perform, for example, an "append" using net.tmorris.adt.sequence.AppendSequence[2] to be provided with a Sequence contract implementation that appears to have had elements appended.
The question arises, if Sequence is immutable, and I get a Sequence that has a greater length with additional elements, how can an element copy *not* occur? The problem here is that the premise of the question is contrived. Specifically, this part "I get a Sequence that has a greater length with additional elements". This did not occur at all since this is an invalid requirement. I merely obtain a contract implementation identity that met some formal requirement. That I have applied additional context by referring to "additional elements" or whatever it might be, is purely for my own convenience in conceptualisation of the software at hand and unrelated. It is important that it be understood the limitations of such a conceptualisation.
That ends my rant. Bye
[ March 09, 2006: Message edited by: Tony Morris ]