I've just found a surprising bug of sorts in my OT code. It turns out
compose has peculiar side effects in terms of information loss / gain.

Imagine you have a compose function '+', infix transform function 'T',
server op 's' and client ops 'c1' and 'c2', its possible that:
s T c1 T c2  !=  s T (c1 + c2)

Wave's concurrency control algorithms never do this, so its not a
problem in practice. Is this normal? It never occurred to me that this
would be the case...

If anyone is curious, I've reproduced this behaviour using WIAB's
docops (below).

-J


... Basically, it happens if
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);

Reply via email to