« Programming as a craft | Main | Querying RDF »
2005-05-02
Adding triples to a Wilbur database
Richard Newman has a good idea of how to add triples to a Wilbur database. Basically, he introduces a function that takes "Lisp-like" descriptions of RDF resources. It's funny, Wilbur used to support a function a bit like this; perhaps the whole idea should be revisited in Wilbur2 (yes, I know, I have said that it's coming, and it really is...).
Richard's function add-triple-list
is, however, a bit too much like a function from, say, Java or C++ "transcribed" into Common Lisp. I couldn't help writing my own (mostly because of my mental disease). So here goes:
(defun db-add-description (db description)
(destructuring-bind (frame &rest slot-and-values) description
(dolist (slot-and-value slot-and-values)
(destructuring-bind (slot &rest values) slot-and-value
(dolist (value values)
(db-add-triple db (triple frame slot value)))))
frame))
(defun db-add-descriptions (db descriptions)
(mapcar #'(lambda (description)
(db-add-description db description))
descriptions))
Basically, db-add-description
takes two parameters: a database instance and a special description of a resource (an rdf:Description
, that is; hence the name of the function). The syntax for the description is
( frame { ( slot { value } * ) } * )
It returns the node affected. The function db-add-descriptions
merely takes a list of special descriptions and returns a list of the nodes affected.
Looking at the code, doesn't it make you think that it would be so nice to have a special version of dolist
that instead of a variable would use a destructuring pattern. We could define it as follows:
(defmacro dolist+ ((pattern list &optional (value nil)) &body body)
(if (symbolp pattern)
`(dolist (,pattern ,list ,value) ,@body)
(let ((i (gentemp)))
`(dolist (,i ,list ,value)
(destructuring-bind ,pattern ,i ,@body)))))
We could now rewrite db-add-description
as follows:
(defun db-add-description (db description)
(destructuring-bind (frame &rest slot-and-values) description
(dolist+ ((slot &rest values) slot-and-values)
(dolist (value values)
(db-add-triple db (triple frame slot value))))
frame))
No big deal, I guess, but I have a bunch of other code where this type of constructs abound.
Posted by ora at 11:55
Comments
You're absolutely right; my abysmal code was the result of (a) never having used destructuring-bind, and (b) being a two-minute hack :D I think it would be worth my while to look at destructuring-bind.
I was aiming for one feature; the ability to either provide a list of values or a single value, just like Notation 3 with its semicolon and comma operators. Your version does this without having to explicitly use lists, which is a benefit.
Add in a declarative prefix form, and you've got a great competitor for N3 :)
Thanks Ora! I'm honoured to have such a valuable critique.
Posted by: Richard Newman at May 2, 2005 05:48 PM
I have noticed one difference, though -- I don't think the solution presented above will deal with a single triple, e.g.
(db-add-description db '(!a:a !a:p !a:o))
which my original code did (i.e. it checks both the properties and objects to see if they are lists before processing them, so at either stage you can present a list or a value). This example must be written as:
(db-add-description db '(!a:a (!a:p !a:o)))
Posted by: Richard Newman at May 2, 2005 06:09 PM
Perhaps the time has come to fulfill one of my original dreams about RDF: an s-expression syntax! XML vs. s-expressions was a subject of lengthy (and at times heated) debates in the original RDF M+S WG. I have often felt that choosing an XML-based syntax for RDF was a big mistake. It has created more confusion than good.
Posted by: Ora Lassila at May 3, 2005 08:29 AM
I think it would be advantageous. There's a relationship between RDF formats and languages, I think... RDF/XML is Java, Notation 3 is Python.
SPARQL feels a little bit like a good C program.
Lisp could do with its own concise format... perhaps this weekend ;)
Posted by: Richard Newman at May 3, 2005 10:22 AM