Greg Stein wrote:

> On Fri, Sep 6, 2013 at 1:47 PM, Philip Martin wrote:
>> [...] I have shown how Ev2 with a split move could
>>  handle the case
>> 
>>     A/B/C to A
>>     A/B to A/B
>>     A to A/B/C
>> 
>>  What is your alternative?
> 
> move(A/B/C@original, A, replace=R)
> move(A/B@original, A/B)
> move(A@original, A/B/C)

Let me try to lay this to rest from another angle.

Look at step 1 of that suggested sequence of three operations.  The implicit 
definition of the single move operation suggested there is something like:

   "Find the subtree that was at path A/B/C at the start of this edit.
   It may still be in the current tree state, possibly at a different path,
   or it may have been deleted earlier in this edit in which case you'd
   better have access to a copy of it from before you deleted it.  If it
   still exists in the current tree state, then move it from where it is
   currently path to 'A'; otherwise, recover a copy of it as it would have
   looked before it was deleted, taking care to omit any child that was
   the source of an earlier move, and write that to path 'A'."

The one significant difference between the "split" (move-away, move-here) 
scheme and the single-move (referring to initial state) scheme can be stated 
like this:

  Before sending a delete operation, do we declare whether that subtree
  will be used as the source of a move later in the edit?

In the example above, the first move deletes the original 'A' by replacing it.  
In the second step, move(A/B@original, A/B) requires the edit consumer to find 
the original A/B, which was deleted by that earlier replacement.  In the 
single-move scheme, the consumer discovers this after having deleted it.

Now consider what it would mean if we amended the solution by inserting, 
right at the beginning of the edit, an operation saying just:

  move-away(A)

Overall, the edit would convey exactly the same information; no new information 
has been added, since that move-away was already implied by steps 2 and 3.  The 
only thing new is the timing of this information.  The consumer would know, 
before replacing 'A' in step 1, that the 'A' being replaced will be needed 
later.  The "split" scheme does exactly that, using the term 'move-here' 
instead of just 'move' for clarity.

In the "split" scheme, the consumer is informed of each move source before 
deleting it.  There is no other significant difference between the schemes.  
(Whether the source and target are identified by a path relative to the current 
state or to the initial state, or given an arbitrary "id", is merely a detail 
of how the API semantics are codified.)

Both schemes are functionally correct.  Both schemes *could* be implemented.  
But not with the same sequential temporal characteristics.

The design of Ev2 is based on the concept of incremental edits to a "current" 
tree state.  I feel that the idea that you could start editing the tree, 
deleting subtrees, and then come to an operation that says "Now please recover 
one of the subtrees that I earlier told you to delete" doesn't fit with that 
philosophy.

The model of operation of the "split-move" scheme is no more split than the 
model implied by the "single-move" scheme; it's just more explicit.  It doesn't 
in any way change or add to the overall semantic content of 
the edit, all it changes is the timing of the information, fore-warning the 
consumer that a forthcoming deletion is not to be regarded as final and 
absolute.  That fore-warning makes a sequential consumer implementation 
feasible.

Does that angle make sense, Greg?

- Julian

Reply via email to