- From: Pierre-Antoine Champin <pierre-antoine.champin@univ-lyon1.fr>
- Date: Mon, 6 May 2019 19:58:14 +0200
- To: Hugo Mills <hugo@carfax.org.uk>
- Cc: "public-json-ld-wg@w3.org" <public-json-ld-wg@w3.org>
- Message-ID: <CA+OuRR_0BgLDNhQAZ6UqK0yLSx48_LfBhEvWiaROmXek16cxeA@mail.gmail.com>
It seems to me that your problem comes, as you suspected yourself, from a wrong transposition of the "mutable" logic of the algorithm to the "imutable" logic of Erlang... In 'usages' (step 4.5.8.2) and 'referenced_onces' (step 4.5.10.1), the 'node' and 'value' members must be **references** to the corresponding nodes, stored elswhere in the node map. So when steps 5.3.4 to 5.3.6 alter the 'head', they alter it *wherever* it sits in the global structure, even if it is inside a `@list` value previously created. Hope this helps On Fri, 3 May 2019 at 22:55, Hugo Mills <hugo@carfax.org.uk> wrote: > Hi, > > I hope this is the right place to ask this. Please advise if it's > not appropriate here. > > I've been trying to write a JSON-LD serialiser, and I've hit an > issue with my code intermittently failing one of the test cases. I > wanted to check whether the problem is actually with my code, or if > it's an ambiguity in the specification. > > The serialisation algorithm in ยง8.4.2 of the draft JSON-LD 1.1 > Algorithms spec seems to produce different results for nested lists, > depending on the order chosen for iterating over the usages of the > rdf:nil node, in part 5.3. > > My understanding of the algorithm is that it find things that look > like an rdf:List, and rolls up the list from the end, while a fairly > large number of conditions (5.3.3) is true. This is relatively easy to > deal with in the case of a single list, and there are lots of test > cases dealing with the various termination conditions. The one I'm > having trouble with is t0008: > > <http://example.com> <http://example.com/property> _:outerlist . > _:outerlist <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> _:lista . > _:outerlist <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:b0 . > > _:lista <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "a1" . > _:lista <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:a2 . > _:a2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "a2" . > _:a2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:a3 . > _:a3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "a3" . > _:a3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> < > http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> . > > _:c0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> _:c1 . > _:c0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> < > http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> . > _:c1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "c1" . > _:c1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:c2 . > _:c2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "c2" . > _:c2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:c3 . > _:c3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "c3" . > _:c3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> < > http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> . > > _:b0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> _:b1 . > _:b0 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:c0 . > _:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "b1" . > _:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:b2 . > _:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "b2" . > _:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:b3 . > _:b3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "b3" . > _:b3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> < > http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> . > > which is, in Turtle, fundamentally this graph: > > <http://example.com> <http://example.com/property> > (("a1" "a2" "a3") > ("b1" "b2" "b3") > ("c1" "c2" "c3")). > > Now, my implementation of the algorithm behaves differently, > depending on whether it decides to roll up any of the sub-lists before > or after it decides to roll up the parent list. If it does the parent > list first, I get the golden output for test 0008: > > [ > ... > { > "@id": "_:lista", > "http://www.w3.org/1999/02/22-rdf-syntax-ns#first": [ { "@value": > "a1" } ], > "http://www.w3.org/1999/02/22-rdf-syntax-ns#rest": [ > { > "@list": [ > { "@value": "a2" }, > { "@value": "a3" } > ] > } > ] > }, > { > "@id": "http://example.com", > "http://example.com/property": [ > { > "@list": [ > { "@id": "_:lista" }, > { "@id": "_:b1" }, > { "@id": "_:c1" } > ] > } > ] > } > ] > > If it does the parent list last, I end up generating the doubly-nested > structure: > > ["@id": "http://example.com", > "http://example.com/property": [{"@list": > [{"@list": > [{"@value": "a1"}, > {"@value": "a2"}, > {"@value": "a3"}]}, > {"@list": > [{"@value": "b1"}, > {"@value": "b2"}, > {"@value": "b3"}]}, > {"@list": > [{"@value": "c1"}, > {"@value": "c2"}, > {"@value": "c3"}] > }] > }] > ] > > If the parent list comes in the middle, I get a hybrid between the > two. > > My problem is that I can't see where in the algorithm this > ambiguous behaviour is prevented. There's nothing that I can see which > stops the first bnode of a list being rolled into the list if it's > also an element in another list. I also can't see anything which > guarantees that higher-level lists are processed before lower-level > lists, which should also generate the correct output for that test. > > What have I missed here? > > [For information, I'm implementing this in Erlang, so I've also > been having trouble converting from a very procedural, > global-data-and-mutable-variables view on the world into a functional, > immutable-variables view. This may be contributing to any > misinterpretation of the algorithm as documented.] > > Thanks, > Hugo. > > -- > Hugo Mills | Great films about cricket: The Third Man > hugo@... carfax.org.uk | > http://carfax.org.uk/ | > PGP: E2AB1DE4 | >
Received on Monday, 6 May 2019 17:58:49 UTC