Re: a few patch challenges

On Mon, Aug 11, 2014 at 9:18 PM, Sandro Hawke <sandro@w3.org> wrote:
> On 08/11/2014 04:12 PM, Alexandre Bertails wrote:
>
> On Mon, Aug 11, 2014 at 11:39 AM, Sandro Hawke <sandro@w3.org> wrote:
>
> Arguably we should have made a patch test suite years ago.
>
> Off the top of my head, here are a few patch challenges.    It's not
> necessarily a requirement that they all be done, but I think it would help
> show the differences to see how they are done in ldpatch, etc.
>
> You can find the result at [1].
>
>
> Impressive, thanks.
>
> Do you have code to generate patches?    I gather you made these ones by
> hand.

I did them by hand. TimBL said he had something doing that, and I
believe one can do a decent job at generating an LD Patch document
from a diff.

That being said, I am not planning to take on this approach as my
applications don't manipulate RDF directly. Instead of manipulating
triples directly, you usually manipulate datastructures/objects in
your favourite language. There are many ways to track effects
happening to them, either a priori or a posteriori. Generating the
patch is much easier in that case. But I digress.

>
> Some syntactic concerns which I've mentioned before.  My apologies if
> there's been a response I missed.   Also, the attendeeOf bug is still there
> in the spec.
>
> 1.  Why these seemingly gratuitous differences from SPARQL path expression:
>
> - instead of ^ for inverse path operator

As we discussed once, nobody is against that change. I proposed that
we'd make that kind of change as a group resolution, after we get the
FPWD.

As we want to save some bits, I would also propose \ (backslash) which
could combine "/-".

>
> paths start with / instead of having it be an infix operator

Actually, it is meant to be infix, where the left operand is a
concrete node (or a set of node). I agree it is a bit awkward in the
path constraints, as the current node(s) is(are) implicit.

Maybe the intent is better understood with a few more spaces: `<node>
/<foo> /-<bar>`.

That plus the path constraints, it has different semantics than SPARQL Path.

>
> ?
>
> 2.  Why > as the slice operator?   It looks like the vast majority [1] of
> languages use colon, and the the rest use "..".   I think either of those
> would be familiar to experienced programmers, unlike >.    I suppose I'd
> pick .. because colon seems too much like a pname, but I'm fine with colon,
> too.
>
> [1] http://en.wikipedia.org/wiki/Array_slicing

Actually, Pierre-Antoine wanted to change that but like other things,
we ultimately decided to stick again to his own original proposal
(that was the plan), so that we can decide as a group which syntax
would be better. At the end of the day, it doesn't really matter :-)

>
> 3.  Why square brackets for filter?   I'd think parens for grouping, then =
> for filter would do it.     Doing that and making / infix (as in sparql)
> instead of prefix, we'd get:

That part just felt quite similar to xpath. Actually the whole path
thing is much closer to xpath than to SPARQL.

>
> Bind ?event <#> schema:attendeeOf/(schema:url =
> <http://conferences.ted.com/TED2009/>)
>
> Alternatively, if you keep square brackets, there's no need for the equal
> sign, either for parsing, or for looking familiar.
>
> --
>
> I think my biggest advice, and this is what keeps making me raise my voice
> during meetings -- for which I'm sorry -- is to understand that you've
> created a new language here, and you have to teach it to your audience.  You
> can't just say "it's just patch".  Your audience is going to take a while to
> learn it, as they do any new language.

It's not just Patch. It is "just" RDF diff + node bindings + support
for rdf:list  :-)

By the way, I am surprised that you didn't come up with more examples
involving rdf:list, because this is a very important part of LD Patch.

>
> I'd suggest giving them a series of increasing examples, such as the test
> cases I posed to you, so they can see that blank nodes get selected from the
> nearest node via forward or backward arcs, then filtered if necessary.

I completely agree. If we decide to move forward with this approach,
it is my very intention that the specification will double as
documentation.

> Which makes me think....

You can find the new tests at [2].

[2] https://github.com/betehess/banana-rdf/blob/efe9ba1a522768ec81649c281f5433096fb90a1d/ldpatch/src/test/scala/SandrosChallenge.scala#L248

>
> == TEST 9
> == FROM
> <alice> <knows >
>      [ <first> "Bob", <last> "Smith" ],
>      [ <first> "Bob", <last> "Jones" ],
>      [ <first> "Charlie", <last> "Smith" ],
>      [ <first> "Charlie", <last> "Jones" ].
> == TO
> <alice> <knows >
>      [ <first> "Bob", <last> "Smith" ],
>      [ <first> "Bob", <last> "Jones" ],
>      [ <first> "Charlie", <last> "Smith" ],
>      [ <first> "Chuck", <last> "Jones" ].
> == END
>
> Every language features needs a test in the test suite, and really should be
> motivated by a use case.   If you allow multiple filters in one path,
> provide an example where that's necessary.  (I think that's what Test 9 is.)

Yes.

>
> And just to push a tiny bit more, to make sure we can step after the filter:
>
> == TEST 10
> Somewhat artificial use of <text> but surely there are situations like this
> == FROM
> <alice> <knows >
>      [ <first> [ <text> "Bob"], <last> [ <text> "Smith"] ],
>      [ <first> [ <text> "Bob"], <last> [ <text> "Jones"] ],
>      [ <first> [ <text> "Charlie"], <last> [ <text> "Smith"] ],
>      [ <first> [ <text> "Charlie"], <last> [ <text> "Jones"] ].
> == TO
> <alice> <knows >
>      [ <first> [ <text> "Bob"], <last> [ <text> "Smith"] ],
>      [ <first> [ <text> "Bob"], <last> [ <text> "Jones"] ],
>      [ <first> [ <text> "Charlie"], <last> [ <text> "Smith"] ],
>      [ <first> [ <text> "Chuck"], <last> [ <text> "Jones"] ].
> == END
>
> Is the value of Bind unique, or can it be a set?

We (the editors) talked a lot about that. The very first draft was
actually binding variables to sets of nodes, and so did my initial
implementation.

In the end, we went back to something much closer to the RDF Patch
solution. That is: Add and Delete only touch one triple at a time.

>   That is, is ! implicit in bind?

Completely spot on. It is part of the semantics. (still not flushed
but I hope you're now convinced that it is not difficult)

>  If not, can every path expression be re-written as a sequence of
> single-step Bind operations?

Well, you could, but don't want to do that: if you could actually
split your path in two, it means that you had a shorter path in the
first place, and that you are better off using that one.

>
> To try my understanding, how's this:
>
> Bind ?CharlieJones "Charlie" /-<text>/-<first>/[/<last>/<text> = "Jones"]!

As you guessed, the trailing ! is not needed.

>
> How about three properties being needed:
>
> == TEST 11
> == FROM
> <alice> <knows >
>      [ <first> "Bob", <middle> "A", <last> "Smith" ],
>      [ <first> "Bob", <middle> "B", <last> "Smith" ],
>      [ <first> "Bob", <middle> "A", <last> "Jones" ],
>      [ <first> "Bob", <middle> "B", <last> "Jones" ],
>      [ <first> "Charlie", <middle> "A", <last> "Smith" ],
>      [ <first> "Charlie", <middle> "B", <last> "Smith" ],
> == TO
> == END
>
> Then I guess we'd use something like:
>
> Bind ?BobASmith <alice> /<knows>[/<first> = "Bob"][/<middle> = "A"][/<last>
> = "Jones"]!
>
> Right?

I used your bind in test11 and it worked right away :-)

Alexandre

>
>        - s
>
>
> All tests that are not about pathological graphs pass with the
> implementation matching the current spec.
> It works both with Jena, and Sesame, and the pure Scala implementation.
>
> Please read the comments inside the code for more information.
>
> Alexandre
>
> [1]
> https://github.com/betehess/banana-rdf/blob/d49e417c6c5560a6a852e587318da4493d25f5b1/ldpatch/src/test/scala/SandrosChallenge.scala
>
>
>       -- Sandro
>
>
> ==TEST 1
> ==FROM
> <alice> <knows> <bob>, <charlie>.
> ==TO
> <alice> <knows> <bob>, <dave>.
> ==END
>
>
> ==TEST 2
> ==FROM
> <alice> <knows> ( <bob> <charlie> )
> ==TO
> <alice> <knows> ( <bob> <dave> )
> ==END
>
>
>
> ==TEST 3
> ==FROM
> <alice> <knows> [ <knows> <bob> ], [<knows> <charlie>].
> ==TO
> <alice> <knows> [ <knows> <bob> ], [<knows> <dave>].
> ==END
>
> ==TEST 4
> ==FROM
> <alice> <knows>
>    [ <name> "Bob" ],
>    [ <name> "Charlie"].
> ==TO
> <alice> <knows>
>    [ <name> "Bob" ],
>    [ <name> "Dave"].
> ==END
>
> ==TEST 5 (two changes: the secound count, and the second street addr)
> ==FROM
> [ a <Order>;
>   <items> (
>      [ <code> "4343"; <count> 1 ]
>      [ <code> "4344"; <count> 3 ]
>      [ <code> "4347"; <count> 3 ]
>   );
>   <shipTo> [
>      a <Address>;
>      <street> [ <num> 32; <name> "Vassar St" ];
>      <city> "Cambridge";
>      <state> "MA";
>      <zip> 02139
>   ];
>   <billTo> [
>      a <Address>;
>      <street> [ <num> 32; <name> "Vassar St" ];
>      <city> "Cambridge";
>      <state> "MA";
>      <zip> 02139
>   ]
> ].
> ==TO
> [ a <Order>;
>   <items> (
>      [ <code> "4343"; <count> 1 ]
>      [ <code> "4344"; <count> 2 ]
>      [ <code> "4347"; <count> 3 ]
>   );
>   <shipTo> [
>      a <Address>;
>      <street> [ <num> 32; <name> "Vassar St" ];
>      <city> "Cambridge";
>      <state> "MA";
>      <zip> 02139
>   ];
>   <billTo> [
>      a <Address>;
>      <street> [ <num> 36; <name> "Vassar St" ];
>      <city> "Cambridge";
>      <state> "MA";
>      <zip> 02139
>   ]
> ].
> ==END
>
>
>
> ==TEST 6
> ==FROM
> <node> <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> 1
> ]]]]]]]]].
> <node> <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> 2
> ]]]]]]]]].
> <node> <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> 3
> ]]]]]]]]].
> <node> <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> 4
> ]]]]]]]]].
> <node> <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> 5
> ]]]]]]]]].
> <node> <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> 6
> ]]]]]]]]].
> <node> <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> 7
> ]]]]]]]]].
> <node> <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> 8
> ]]]]]]]]].
> <node> <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> 9
> ]]]]]]]]].
> ==TO
> <node> <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> 1
> ]]]]]]]]].
> <node> <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> 2
> ]]]]]]]]].
> <node> <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> 3
> ]]]]]]]]].
> <node> <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> 4
> ]]]]]]]]].
> <node> <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> 5
> ]]]]]]]]].
> <node> <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> 6
> ]]]]]]]]].
> <node> <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> 7
> ]]]]]]]]].
> <node> <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> 8
> ]]]]]]]]].
> <node> <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> [ <p> 0
> ]]]]]]]]].
> ==END
>
> ==TEST 7
> ==FROM
> _:x <a> _:y.
> _:y <a> _:z.
> _:z <a> _:x.
> ==TO
> _:x <a> _:y.
> _:y <a> _:z.
> _:x <a> _:z.
> ==END
>
> ==TEST 8
> ==FROM
> <node> <p> [ <p> [ <p> [ <p> "1" ],
>                        [ <p> "1" ]] ,
>                  [ <p> [ <p> "1" ]]],
>            [ <p> [ <p> [ <p> "1" ]  ,
>                        [ <p> "1" ]],
>            [ <p> [ <p> [ <p> "1" ]]].
> ==TO
> <node> <p> [ <p> [ <p> [ <p> "1" ],
>                        [ <p> "1" ]] ,
>                  [ <p> [ <p> "1" ]]],
>            [ <p> [ <p> [ <p> "1" ]  ,
>                        [ <p> "1" ], [ <p> "1" ],
>            [ <p> [ <p> [ <p> "1" ]]].
> ==END
>
>
>

Received on Tuesday, 12 August 2014 11:39:04 UTC