- From: Mark Birbeck <mark.birbeck@formsPlayer.com>
- Date: Wed, 14 Nov 2007 23:14:11 +0000
- To: Ben Adida <ben@adida.net>
- Cc: RDFa <public-rdf-in-xhtml-tf@w3.org>
Hi Ben, I've written and re-written the following post umpteen times, over the last month or so. :) Finally, I've decided that the best way to break this down is to explain why I disagree with your approach, and then separately to spell out the extra couple of rules we need to make your use-cases work. All attempts I've made to mix the two have been even longer than this email...and as you can see below, this shortened version is still pretty long! So, here goes... You wrote: > Manu wanted me to express my proposed @instanceof rules in a way > similar > to what he recently posted [1], so that we could compare. > > The main driver for my rules is to make it easy for @instanceof to be > used on chaining nodes, so that one can say "I know a person named > 'Ralph'", or even the more complicated "I know a person who knows a > person who knows a person named 'Bill'". The statements: I know a person named 'Ralph' and: I know a person who knows a person who knows a person named 'Bill' were both always possible in earlier versions of RDFa, and in my view, in a way that is simpler than in your proposal. So before I go into that, some context. CONTEXT What I believe has happened is this; chaining was removed from RDFa in the first draft that was produced within the taskforce, because it was deemed too complicated. After a while--and probably many use- cases :) --you proposed the idea that @href, @src, etc., should set the subject of contained statements, which was both an insightful idea, and effectively a 'reintroduction' of chaining. :) However, there are a number of other aspects to chaining that need to be 'reintroduced' if we are to make it completely consistent, and I think it is the lack of these that makes your proposal not quite hang together (in my view). I don't think I can explain them all in this posting, but what I do think is important to do first--which I will do here--is to explore the problems with your 'rules', and to look at why I think they create unnecessary inconsistencies with attribute behaviour, without any gain. (Sorry to put it so bluntly!) CONSISTENCY I'll begin with your first statement, that: I know a person called Ralph To indicate this, if we had all of the 'old' chaining rules in RDFa, then *any* of the following constructs could be used: ======== <div about="#me"> <div rel="foaf:knows"> <div instanceof="foaf:Person"> <span property="foaf:name">Ralph</span> </div> </div> </div> ======== ======== <div about="#me"> <div rel="foaf:knows"> <span property="foaf:name" instanceof="foaf:Person">Ralph</span> </div> </div> ======== ======== <div about="#me" rel="foaf:knows"> <div instanceof="foaf:Person"> <span property="foaf:name">Ralph</span> </div> </div> ======== ======== <div about="#me" rel="foaf:knows"> <span property="foaf:name" instanceof="foaf:Person">Ralph</span> </div> ======== Note the consistency as the mark-up is expanded and contracted--by which I mean that elements are added and removed--the rules always stay the same, regardless of the presence of other attributes. In fact, if you removed the _elements_ and left behind only the attributes, every single one of these constructs results in the same structure: about="#me" rel="foaf:knows" {bnode} instanceof="foaf:Person" property="foaf:name" content="Ralph" This is obviously desirable, and is no accident. Before I look at your rules in more depth, Ben, I'd like to continue to demonstrate the consistency of the 'complete' set of chaining rules that we used to have (which as I said, I'll go into in another thread). We'll take as our starting-point the last piece of mark-up, i.e., this one: ======== <div about="#me" rel="foaf:knows"> <span property="foaf:name" instanceof="foaf:Person">Ralph</span> </div> ======== and use it as a base from which to build up to your more complicated scenario: I know a person who knows a person who knows a person named 'Bill' However, let's make the example slightly more realistic, by adding more information--we'll give each of the people down the chain a name, as follows: I know a person named 'Ralph', who knows a person named 'Ivan', who knows a person named 'Bill' Having established where we're heading, we need to do one last minor piece of preparation, and that is to slightly reorganise the mark-up so that we use @content instead of an inline literal; this makes the examples easier to read as they get more complex, and of course, it makes it easier to 'nest' elements, one inside the other. So, our first statement, from which we will build up, now looks like this: ======== <div about="#me" rel="foaf:knows"> <span instanceof="foaf:Person" property="foaf:name" content="Ralph" > </span> </div> ======== The next step is to simply cut-and-paste Ralph (painless, I hope), in order to create a third person that looks exactly like the second one, but with the name value set to 'Ivan': ======== <div about="#me" rel="foaf:knows"> <span instanceof="foaf:Person" property="foaf:name" content="Ralph" > <span instanceof="foaf:Person" property="foaf:name" content="Ivan" > </span> </span> </div> ======== Note that the only difference between this 'person' and the one we already had was that @content is set to 'Ivan' instead of 'Ralph', but the structure is exactly the same. Once we've added this extra 'person' item, all we should have to do is to add an additional predicate to the second item (i.e., Ralph), to indicate the relationship between the two people: ======== <div about="#me" rel="foaf:knows"> <span instanceof="foaf:Person" property="foaf:name" content="Ralph" rel="foaf:knows" > <span instanceof="foaf:Person" property="foaf:name" content="Ivan" > </span> </span> </div> ======== As you can see, the only difference between the mark-up that expressed two _unconnected_ people (i.e., the previous step), and the mark-up that has two _connected_ people, is at line 5; it is there that we have added the extra predicate to the second item (Ralph) that indicates a relationship with the third item (Ivan). The first thing that is important here--although the significance is probably quite obvious--is the way that I created the 'inner' item by cutting-and-pasting an item from elsewhere; the consistency of the language means that you can just 'drop' items from different places into position. In addition, we can keep adding child elements, getting deeper and deeper, as much as we like. The second thing that is worth noting is that adding the @rel to establish the relationship between the two items is nothing more than adding a predicate to an item, and so does not change that item in any way. I'll say more on this below, but at this point the key thing to note is that adding and removing the @rel only changes the relationship between the items, and changes nothing about the item itself. Anyway, let's continue, and finish your more complex scenario; we need to add: Ivan knows a person called 'Bill' As before, first we add a self-contained 'person' item: ======== <div about="#me" rel="foaf:knows"> <span instanceof="foaf:Person" property="foaf:name" content="Ralph" rel="foaf:knows" > <span instanceof="foaf:Person" property="foaf:name" content="Ivan" > <span instanceof="foaf:Person" property="foaf:name" content="Bill" > </span> </span> </span> </div> ======== and then, as before, we add the relationship between Ivan and Bill: ======== <div about="#me" rel="foaf:knows"> <span instanceof="foaf:Person" property="foaf:name" content="Ralph" rel="foaf:knows" > <span instanceof="foaf:Person" property="foaf:name" content="Ivan" rel="foaf:knows" > <span instanceof="foaf:Person" property="foaf:name" content="Ben" > </span> </span> </span> </div> ======== SUMMARY OF POSITION Now, hopefully what's obvious after having carried out the same process twice is that: * the attributes behave consistently; * @instanceof always applies to the subject on an element (possibly a bnode), and not the object. In this, therefore, it does not differ from the setting of any other predicate; * items can be easily cut from one document and dropped into another, as self-contained building-blocks that stand in relation to other items; * adding a relationship between one item and another does not change anything about the items. I think all of these are important arguments, and each of them presents a strong case against making @instanceof behave in the way that you want, Ben. But I think the most significant is the last, which I mentioned earlier, and said I'd return to. ESTABLISHING A RELATIONSHIP SHOULDN'T CHANGE AN ITEM'S MEANING So, to illustrate what I mean by saying that 'adding a relationship changes the meaning of the items', let's rewind to the beginning of my steps, and this time we'll use your rules instead of my 'old' RDFa rules. Also, since I'm not 100% certain that we agree on the meaning of the mark-up I've used as my starting-point, I've scoured all the discussions for a piece of mark-up that both sets of rules agree on, and found this (the initial comment is yours, just to put the mark-up into context): "And if you wanted to declare #me a foaf:Person, you would write it with two elements: <div about="#me" instanceof="foaf:Person"> <div rel="foaf:knows"> <span property="foaf:name">Ralph</span> </div> </div>" I think we agree that in both sets of rules this snippet means: I am a person who knows something named 'Ralph' As before I'll use @content to make things easier to read, giving us this: ======== <div about="#me" instanceof="foaf:Person"> <div rel="foaf:knows"> <span property="foaf:name" content="Ralph"> </span> </div> </div> ======== Now, we're ready to proceed pretty much as before. Let's say that Ralph knows Ivan; we know that Ivan can be identified by "http://www.w3.org/People/Ivan/#me", so it should be pretty straightforward to add @rel="foaf:knows", as follows: ======== <div about="#me" instanceof="foaf:Person"> <div rel="foaf:knows"> <span property="foaf:name" content="Ralph" rel="foaf:knows" href="http://www.w3.org/People/Ivan/#me" > </span> </div> </div> ======== This inner element is quite a nice, self-contained block. At the moment it could be passed around from one document to another in its self-contained form: ======== <span property="foaf:name" content="Ralph" rel="foaf:knows" href="http://www.w3.org/People/Ivan/#me" > </span> ======== No matter where it appears it should mean the same thing--this is the 'cut-and-paste' point I made earlier. But what if we want this self-contained block to also indicate that Ralph is a person? In earlier versions of RDFa we could have added a child <link>, as follows: ======== <span property="foaf:name" content="Ralph" rel="foaf:knows" href="http://www.w3.org/People/Ivan/#me" > <link rel="rdf:type" resource="[foaf:Person]" /> </span> ======== However, as we know, due to browser limitations we've had to remove this feature--the rule that allows '<link> and <meta> everywhere-- from the current version of RDFa , although it is still present in XHTML 2's use of RDFa. There was an additional design principle, though, that <link> as a child element was actually a longhand version of adding an attribute to the element, so the previous mark-up *should be* the same as this: ======== <span property="foaf:name" content="Ralph" rel="foaf:knows" href="http://www.w3.org/People/Ivan/#me" instanceof="foaf:Person" > </span> ======== That's a slight diversion, but essentially my point is that since @instanceof is the renamed @class, and @class was always understood to be a shorthand for a child <link> element, then it is easy to see why the type and all predicates should be applied to the same subject. (And conversely, it is a very big leap to suggest that instead we should apply @instanceof to the _object_ rather than the _subject_, since there is nothing in the general architecture of RDFa that gives a precedent for that.) So, your rules effectively suggest that @instanceof no longer applies to the subject of the element as it used to, but is now applied to the 'thing' being referred to, in this case Ivan. So if we wanted to indicate that 'the thing named Ralph' is a person, we would have to wrap the mark-up in another element, and put the type onto that element. In other words, we would have to go from this: ======== <span property="foaf:name" content="Ralph" rel="foaf:knows" href="http://www.w3.org/People/Ivan/#me" > </span> ======== to this: ======== <span instanceof="foaf:Person"> <span property="foaf:name" content="Ralph" rel="foaf:knows" href="http://www.w3.org/People/Ivan/#me" > </span> </span> ======== You could say that this is not onerous, but it's not the extra mark- up that is the problem, it's the justification; we're asking authors to create an extra containing element, only because there is a resource predicate sitting on the element that represents the item that we want to set the type of. If the element didn't have a resource predicate: ======== <span property="foaf:name" content="Ralph" > </span> ======== then we'd be allowed to add the type information to the same element as the one containing the literal: ======== <span instanceof="foaf:Person" property="foaf:name" content="Ralph" > </span> ======== In other words, there would be no need for the containing element. In my mind this kind of restriction is a world away from the rules I showed at the beginning where all sorts of different pieces of mark- up represented exactly the same set of triples. MORE COMPLEX Anyway, let's continue with this item--a self-contained item which is now 'a person named Ralph'. Given such an item, we'd expect to be able to put this anywhere we like, without any unexpected side- effects. So to continue our example, let's drop it into the the mark- up we were looking at earlier: ======== <div about="#me" instanceof="foaf:Person"> <div rel="foaf:knows"> <span instanceof="foaf:Person" property="foaf:name" content="Ralph" > </span> </div> </div> ======== We now have: I am a person who knows a person named 'Ralph'. Let's duplicate Ralph, change the name to Ivan, and paste this into the empty <span> element that represents Ralph: ======== <div about="#me" instanceof="foaf:Person"> <div rel="foaf:knows"> <span instanceof="foaf:Person" property="foaf:name" content="Ralph" > <span instanceof="foaf:Person" property="foaf:name" content="Ivan" > </span> </span> </div> </div> ======== At the moment there is no relationship between the two items, and all we have is this: I am a person who knows a person named 'Ralph' There is a person named 'Ivan' This is pretty much the same as we had when building this up using my rules, and as before, we want to now continue on, heading for the same complex statement about Ralph, Ivan and Bill that we had above. So now we need to say that not only do 'I know Ralph', but also that 'Ralph knows Ivan'. We know that to express this relationship we need to use @rel="foaf:knows", so the question is quite simply, where should we put this attribute? Since the predicate we are expressing ('foaf:knows') is a property of Ralph, then it would seem to make sense to add the attribute to Ralph's <span>: ======== <div about="#me" instanceof="foaf:Person"> <div rel="foaf:knows"> <span instanceof="foaf:Person" property="foaf:name" content="Ralph" rel="foaf:knows" > <span instanceof="foaf:Person" property="foaf:name" content="Ivan" > </span> </span> </div> </div> ======== In the rules as they used to be, and as I showed above, this gives the desired result, with no side-effects. But with the rules you are proposing, Ben, although adding the @rel at this position creates the desired _relationship_ between the two items, it causes a number of very awkward things to happen. SIDE-EFFECTS First, Ralph's @instanceof suddenly 'moves' from applying to him, to now applying to the bnode that the @rel creates. In other words, one moment Ralph is a person, the next he isn't, and all the author did was to try to place the item representing Ralph into a relationship with some other item. Secondly, in your rules we are saying that 'Ivan is a person', twice. Now you could argue that in order to create the explicit relationship that we want, we have to mark things up differently to this, according to your rules; after all, the fact that your rules don't give the same results as mine is the whole point of the discussion. :) So once again, to make things work we have to introduce an extra mediating element: ======== <div about="#me" instanceof="foaf:Person"> <div rel="foaf:knows"> <span instanceof="foaf:Person" property="foaf:name" content="Ralph" > <span rel="foaf:knows"> <span instanceof="foaf:Person" property="foaf:name" content="Ivan" > </span> </span> </span> </div> </div> ======== Essentially we've had to add the extra element in between the two items, with @rel on it. Admittedly, as I said before, that's not an enormous amount of extra mark-up, but the real problem I have with this is that it is something that an author *must* do; it's not just a coding convention, or something that makes things a little easier to read, but is actually something that if the author _didn't_ do it, then their mark-up would mean something completely different to what they wanted it to mean. SIMPLE PATTERNS But the worse thing about this is that it breaks the simple pattern that we have in RDFa, and it raises the question, why is @rel allowed to accompany its subject on statements like "I know a person named 'Ralph'": ======== <div about="#me" rel="foaf:knows"> <span instanceof="foaf:Person" property="foaf:name" content="Ralph" > </span> </div> ======== but it is not allowed to accompany its subject on the next statement, "Ralph knows a person named 'Ivan'"? The mark-up for that looks like this: ======== <div about="#me" rel="foaf:knows"> <span instanceof="foaf:Person" property="foaf:name" content="Ralph" rel="foaf:knows" href="http://www.w3.org/People/Ivan/#me" > <span instanceof="foaf:Person" property="foaf:name" content="Ivan" > </span> </span> </div> ======== and although it works fine with my rules (we get "I know a person named 'Ralph' who knows a person named 'Ivan'"), when using your rules it is not intuitive at all why the @instanceof on the 'Ralph item' should suddenly 'jump' to begin applying to Ivan. PREDICATE PERMUTATIONS To put this in a different way again, it's worth looking at what is the limit of what an element can express, as follows. Under normal circumstances, an element can obviously have a subject, but then on top of that, an element could have a maximum of three predicates, i.e., a literal, a resource, and an rdf:type. However, with your rules we have to effectively say that not all permutations are possible, and instead say that an element can only have a maximum of two predicates to accompany the subject. The permutations are as follows: * a literal on its own; * a resource on its own; * a type on its own; * a literal and a resource; * a literal and a type. After that, when using your rules the remaining two permutations are unavailable: * a resource and a type; * a literal, a resource and a type. This is because the moment you add a predicate that takes a resource-- as we did here by saying that Ralph knows Ivan--the type value no longer applies to the subject. What I've tried to show in the way that the examples have gradually built up, adding a small piece of mark-up at a time, is that this restriction is unfair to authors; why should taking a self-contained item and adding a predicate to it change the meaning of that item? BUCKAROO This 'flip/flop' behaviour reminds me of the children's game Buckaroo, where adding just one more item to the donkey's saddle can make it suddenly kick its hind legs in the air, throwing everything off its back that the players have added. :) In the case of your rules, adding @rel when @instanceof is already present, causes everything to be thrown into the air. You might argue that I'm putting this a little strongly, and that it's not just _any_ relationship between two items that causes a problem, but rather it's the specific 'hierarchical' relationship that we've been using so far (i.e., where one <span> is inside another). But I'm afraid that's not the case, and even if we remove this hierarchy, the problem remains. Let's rewrite the items for Ralph and Ivan so that they appear side- by-side, and let's also give Ivan the identifier that he uses: ======== <span instanceof="foaf:Person" property="foaf:name" content="Ralph" > </span> <span about="http://www.w3.org/People/Ivan/#me" instanceof="foaf:Person" property="foaf:name" content="Ivan" > </span> ======== Combining both pieces of mark-up, both your rules and mine would agree with the following interpretation: There is a person named 'Ralph' There is a person named 'Ivan', identified by the resource <http:// www.w3.org/People/Ivan/#me> Now, if we wanted to add the fact that Ralph knows Ivan, once again it would seem obvious to put the relationship information directly onto Ralph's <span>, as follows: ======== <span instanceof="foaf:Person" property="foaf:name" content="Ralph" rel="foaf:knows" resource="http://www.w3.org/People/Ivan/#me" > </span> ======== But now, once again, simply by expressing a relationship between two items, the rules you are proposing cause a change in the actual *meaning* of one of those items; in this case, Ralph is no longer a 'person', because the moment that you added the @rel/@resource combination, the @instanceof attribute 'flips' to applying to Ivan. And note also that the Buckaroo doesn't just happen with the use of @rel and @instanceof. Let's return to the mark-up describing Ivan: ======== <span about="http://www.w3.org/People/Ivan/#me" instanceof="foaf:Person" property="foaf:name" content="Ivan" > </span> ======== We agree that this means: There is a person named 'Ivan', identified by the resource <http:// www.w3.org/People/Ivan/#me> Let's add that Ivan knows Ralph: ======== <span about="http://www.w3.org/People/Ivan/#me" instanceof="foaf:Person" property="foaf:name" content="Ivan" rel="foaf:knows" resource="http://www.w3.org/People/Ralph/#me" > </span> ======== Again, we should agree that this means: There is a person named 'Ivan', identified by the resource <http:// www.w3.org/People/Ivan/#me> who knows something identified by the resource <http://www.w3.org/ People/Ralph/#me> Everything looks fine, so far...now try removing the @about value, perhaps to include this block somewhere else. Unfortunately, we once again get a flip/flop of meaning--a Buckaroo--since the mark-up without @about means something completely different: ======== <span instanceof="foaf:Person" property="foaf:name" content="Ivan" rel="foaf:knows" resource="http://www.w3.org/People/Ralph/#me" > </span> ======== In your rules Ben, this means: Something with a name of 'Ivan' knows a person identified by the resource <http://www.w3.org/People/Ralph/#me> With my rules, removing @about has no effect on the general meaning, which seems to me reliable and predictable--all removing the identifier does to our item is to remove the identifier. :) In other words, from this: There is a person named 'Ivan', identified by the resource <http:// www.w3.org/People/Ivan/#me> who knows something identified by the resource <http://www.w3.org/ People/Ralph/#me> we simply get this: There is a person named 'Ivan' who knows something identified by the resource <http://www.w3.org/People/Ralph/#me> AVOIDING THE US OF ALL ATTRIBUTES AT THE SAME TIME I know that you've suggested before that you wouldn't put all of the RDFa attributes onto one element in the way that I have done here, but I'm afraid I don't think that is a legitimate argument, for three reasons. First, as we just saw, there is actually no problem when *all* attributes are present, so the argument would need to be that we should avoid using 'most attributes'. :) But seriously, the problem in the last example I gave didn't arise until we went from using every attribute to removing @about. Likewise, in our earlier examples the problem arose when we tried to add @rel to an element that already had @instanceof, and so again was not a problem of having 'all' attributes. The second reason is that the rules need to be consistent under all circumstances, and we can't simply say to people that they should avoid certain patterns because they don't behave in the way that they are expected to. But the third reason is that I've not actually picked outlandish examples here--I've used the examples that you've suggested Ben, so as to create as much common terrain as possible. I hope you can see from these examples that having lots of attributes present is really not that unusual. CONCLUSION I think the fact that you effectively came up with the same idea as chaining a 'second time' is pretty impressive! But I think that if we are to reintroduce it--which I'm mostly in favour of--we need to grab a couple of extra rules that we're currently missing. I think it's worth looking at those in a separate thread, since I don't think it affects this discussion; at core, this thread is about whether @instanceof should apply to the object on an element, if present, and as I've tried to argue, I think it would be a big mistake if we made our attributes behave inconsistently in order to support that rule, especially when we can actually fulfill all of the use-cases that you (rightly) require. Regards, Mark -- Mark Birbeck, formsPlayer mark.birbeck@formsPlayer.com | +44 (0) 20 7689 9232 http://www.formsPlayer.com | http://internet-apps.blogspot.com standards. innovation.
Received on Wednesday, 14 November 2007 23:14:45 UTC