- 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