Shared publicly  - 
 
New blog entry: "RDF lists and SPARQL." Please add any comments here. http://www.snee.com/bobdc.blog/2014/04/rdf-lists-and-sparql.html
3
2
Roberto García's profile photoBob DuCharme's profile photoKurt Cagle's profile photoBello Shehu's profile photo
7 comments
 
Okay!  Now what we need is a little Lisp interpreter that uses a triple store as its object heap.
 
I think I am now (for the first time in my RDF career) in the position that I might actually want a bunch of rdf:first and rdf:next triples.  Here's the situation (leaving out industry-specific stuff).

There are things called Nodes, which are grouped.  We group them into Lists and we group Lists into Groups.  Each of these things is ordered. 

Any node is expected to participate in several Lists, and any List is expected to participate in several Groups. 

So - I can specify the ordering using rdf:Seq and rdf:_1, rdf:_2 etc.  There are issues with this that I won't go in to, unless the discussion goes that way. 

The option of putting a ordering property on Node or List (e.g., "rank") won't work, since a particular Node will be in a different position in different Lists, and a particular List will be in a different position in different Groups. 

So - that leaves some sort of linked list, which ought to use rdf:first, rdf:next and rdf:nil (there's no reason to re-invent that wheel, is there?).  

But this means that I really need the query that will return all the members of the list along with their position.  Or at least, to have a guarantee of getting these things out in list order (e.g., for the UI).

So this might actually be an example where I need the rdf:List structure.  If so, it is the first time I've needed it in about 10 years of using RDF. 
 
FWIW, I have a solution in the space of Bob's example:

SELECT ?item (COUNT (?x))
WHERE {
  d:myList d:contents/rdf:rest*/rdf:first ?item .
  d:myList d:contents/rdf:rest* ?x .  ?x rdf:rest*/rdf:first ?item 
}   GROUP BY ?item
ORDER BY DESC (COUNT (?x))



This works to return the terms in any order according to the ORDER BY.  But I think you'll agree that this approach (count how many things are in between?) is pretty problematic. 
 
Hi Bob - this is a very interesting blog entry, and timely too, in that the W3C Hydra working group is currently discussing this very issue in relation to describing 'Collections' for generic Web APIs via RDF (since nearly every Web API out there needs to describes Lists of things, like your list of friends, the list of items in your shopping cart, lists of search results, etc, etc.).

Have you heard of Hydra (http://www.w3.org/community/hydra/)? Google's Sam Goto has been involved on behalf of Schema.org, so Hydra's ideas could become a very important contribution to the wider RDF community. It would be fantastic to get your input on the current discussions on the mailing list...!
 
Hi Bob,

One could simplify your example queries as follows.

Inserting a new member at a specific position:

PREFIX d: <http://learningsparql.com/ns/data#>
DELETE {
  ?insertionPoint rdf:rest ?rest . 
}
INSERT {
  ?insertionPoint rdf:rest _:b1 . 
  _:b1 rdf:first "threePointFive" ; rdf:rest ?rest . 
}
WHERE {
  d:myList d:contents/rdf:rest/rdf:rest ?insertionPoint .
  ?insertionPoint rdf:rest ?rest . 
}

Deleting a member from a specified position:

PREFIX d: <http://learningsparql.com/ns/data#>
DELETE {
  ?previousMember rdf:rest ?deletionPoint .
  ?deletionPoint rdf:first ?item ;  rdf:rest ?rest .
}
INSERT {
  ?previousMember rdf:rest ?rest.
}
WHERE {
  d:myList d:contents/rdf:rest ?previousMember .
  ?previousMember rdf:rest ?deletionPoint .
  ?deletionPoint rdf:first ?item ;  rdf:rest ?rest .
}

In the second example this also avoids deleting all other triples where ?item is in the subject or object position (unless this is what one wishes to achieve of course :-P)
Add a comment...