Yes, that's why it's specifically inserts that occur after deletes.  In that 
example you insert the 'goodbye' before deleting the 'hello', there is known 
information about the position of the insertion relative to the position of the 
deletion.  It is only when you delete then insert that there must be extra 
information added by the Composer.

It's sort of similar to how when there are two simultaneous insertions the 
Transformer has to make an arbitrary decision about what order to insert the 
two pieces of text, when the position information has been destroyed by a 
previous operation then the Composer has to make an arbitrary decision about 
whether the insertion should be before or after the deletion.

This similarity is what makes me think that there might need to be a different 
Composer for client and server side.  Just as the Transformer treats client and 
server ops differently, so too would the Composer have to treat client and 
server ops differently.

Its been awhile since I've looked at all this stuff so I could be wildly off 
here, but I think that makes some sort of sense.  I might get my Transformer 
fully tested and get the Composer up and running this week if all goes to plan, 
then I'll have an independent implementation that we could compare with.
--
Wim Looman
[email protected]


On 6/03/2011, at 8:36 PM, Joseph Gentle wrote:

> Yep, you're absolutely right about why it happens, although its not
> that easy to fix.
> 
> Sometimes there actually _is_ information in the order of inserts and deletes.
> 
> Say the document looks like this:
>  "hello"
> 
> .. and I do two ops: I insert 'goodbye' before the 'hello' and delete
> the 'hello':
> op1: [insert:'goodbye', skip:5]
> op2: [skip:7, delete:'hello']
> -> "goodbye"
> While you insert characters after the hello:
> [skip:5, insert:"mum"]
> -> "hellomum"
> 
> If you compose my ops together, they become [insert:'goodbye',
> delete:'hello']. And they have to be that way around. If they weren't,
> its possible for your 'mum' to appear before my 'goodbye'. .... which
> just doesn't make sense.
> 
> If you swap deletes and inserts around in ambiguous situations in the
> composer (like the example), you don't remove the problem. You just
> need slightly different ops to demonstrate it.
> 
> -J
> 
> 
> On Sun, Mar 6, 2011 at 9:14 AM, Wim Looman <[email protected]> wrote:
>> I believe this is caused by the Composer and Transformer working slightly 
>> differently.
>> 
>> Basically by placing the insert after the delete the Composer is encoding 
>> non-existent information about the location of the insert, namely that it 
>> was inserted after the location of the delete.
>> 
>> Whereas the Transformer receiving `c1` then `c2` will be working on the 
>> assumption that the 'c' was inserted to the left of the delete location.
>> 
>> So based on this one example I think having the Composer place inserts that 
>> occur after deletes to the left of the deletes would work, however I think 
>> this could break depending on if the composition is happening on the server 
>> side or the client side.
>> --
>> Wim Looman
>> [email protected]
>> 
>> 
>> On 5/03/2011, at 9:43 PM, Joseph Gentle wrote:
>> 
>>> On Sat, Mar 5, 2011 at 6:45 PM, Joseph Gentle <[email protected]> wrote:
>>>> s = insert: 's', skip: 1
>>>> c1 = delete: 'x'
>>>> c2 = insert: 'c'
>>>> 
>>>> 
>>>>    // Make println() usable.
>>>>    DocOpScrub.setShouldScrubByDefault(false);
>>>> 
>>>>    DocOp s = new DocOpBuilder().characters("s").retain(1).build();
>>>> 
>>>>    DocOp c1 = new DocOpBuilder().deleteCharacters("x").build();
>>>>    DocOp c2 = new DocOpBuilder().characters("c").build();
>>>> 
>>>>    DocOp cc = Composer.compose(c1, c2);
>>>> 
>>>>    // s_ = s T c1
>>>>    DocOp s_ = Transformer.transform(c1, s).serverOp();
>>>>    // s__ = s T c1 T c2
>>>>    DocOp s__ = Transformer.transform(c2, s_).serverOp();
>>>> 
>>>>    // cc = c1 + c2
>>>>    System.out.println("cc: " + cc);
>>>>    // scc_ = s T (c1 + c2)
>>>>    DocOp scc_ = Transformer.transform(cc, s).serverOp();
>>>> 
>>>>    // s__ and scc_ are different!
>>>>    System.out.println("s__: " + s__);
>>>>    System.out.println("scc_: " + scc_);
>>>>    System.out.println();
>>>> 
>>>>    // ... And not just different syntactically. They're different 
>>>> semantically.
>>>>    DocOp doc1 = Composer.compose(ImmutableList.of(new
>>>> DocOpBuilder().characters("x").build(), c1, c2, s__));
>>>>    System.out.println("doc1: " + doc1);
>>>> 
>>>>    DocOp doc2 = Composer.compose(ImmutableList.of(new
>>>> DocOpBuilder().characters("x").build(), cc, scc_));
>>>>    System.out.println("doc2: " + doc2);
>>>> 
>>> 
>>> How rude of me!
>>> 
>>> Output:
>>> 
>>> cc: [--"x"; ++"c"; ]
>>> 
>>> s__: [__1; ++"s"; ]
>>> scc_: [++"s"; __1; ]
>>> ^----- You would expect these last two to be equivalent
>>> 
>>> doc1: [++"cs"; ]
>>> doc2: [++"sc"; ]
>>> ^----- .... and these to be identical.
>> 
>> 

Reply via email to