By Michael Kay on February 14, 2006 at 02:18p.m.

Interesting query submitted by a Saxon-SA XQuery user yesterday. They were reporting a bug in validating QNames in element content, but the thing that interested me was that they had written a rather complex function to determine whether two atomic values were equal, without failing if the values aren't comparable.

If you test [@x eq 6], and @x is defined with a union type that allows both strings and numbers, then you'll get a type error if @x happens to contain a string. (With strict static typing, the query won't even compile). The same is true if you use the "=" operator. So this user had coded a complex set of nested typeswitch expressions to ensure that comparing two non-comparable values returned false rather than an error.

In fact there's an easier way. In fact, there are at least two easier ways. Both the following expressions achieve the required aim:

count(distinct-values((@x, @y))  eq 1

exists(index-of(@x, @y))

That's because in both distinct-values() and index-of(), we explicitly decided that non-comparable values should be treated as distinct, rather than causing an error.

Why the difference? It's classic symptom of committee design. For "eq" and "=", the advocates of strong typing won the argument, for distinct-values() and index-of() the weak typists (probably me in this case) swayed the vote. Perhaps it just depended on who was paying attention when the matter came up for discussion.

There are arguments both ways. There's even an argument for making different language features inconsistent with each other, so users can pick and choose! It doesn't feel like a very elegant piece of design, but it's nice to discover that there's a way of doing what's needed in this particular case.