Andrew Welch wrote:
The difference there is that (1 to 2) != 10 returns a sequence of 2
items "true true", whereas (1,2) != 10 returns a single "true". I
would have to look it up but I think anything other than a single
"true" converts to false, so "true true" returns false.
You could rewrite it as ((1 to 2) != 10) = false() to check the values
in the sequence for any occurance of false(), and return a single
true/false.
I read an reread it, and in either case misread it. But now I see my
mistake, and it is pretty simple really (well, it took me a couple of
hours, hope that others grasp it quicker ;) Let's put my thoughts to paper.
The idea is (the way I see it), to find all possible combinations with
your operator in between. Like this (what is left stays left and what is
right stays right):
(a, b) = (c, d)
> a = c or
a = d or
b = c or
b = d
Which follows the rule as Michael put it in his book: "if any operand
satisfies the operator the result of the operation is true". I had
trouble following the same logic for !=, but in case anybody is
listening in, this is how it finally sank in for me, following the same
logic:
(1, 2) != (1, 2)
> 1 != 1 or
1 != 2 or
2 != 1 or
2 != 2
Because at least one of these operations returns true, the result is
*true* (in English: a group of John and Jim is not equal to the same
group of John and Jim). So, even if it looks, at first sight, extremely
odd, using the same logic as with the = operator, it follows that (1, 2)
is NOT equal to (1, 2) (but that's why we have the deep-equal function).
This also explains why the following is always propagated as the best
alternative for finding unequality for all operands:
not ((1, 2) = (1, 2))
> not( 1 = 1 or
1 = 2 or
2 = 1 or
2 = 2 )
Which will return *false*, because at least one of these operands is
true. Often I read that people intuitively and wrongly expect this
not-operation to be the same as the != operation. As a mnemonic, you can
reverse the logic created with not(), making it easier to read:
not ((1, 2) = (1, 2))
> 1 != 1 and
1 != 2 and
2 != 1 and
2 != 2
Which (surprise) returns *false* also. I find this second way of
'writing out' easier to read.
To summarize, using the != operator on sequences, will only return
'false' if all operands are equal, in all other situations it will
return true:
(3, 3, 3, 3) != (3, 3, 3, 3)
> false
(3, 3, 3, 3) != (3)
> false
(3, 3, 3, (), (), 3) != (3, 3, 3, 3)
> false
The last one shows that items that are an empty sequence are discarded.
All above situations are of the spurious kind where reversing the
operator also reverses the result (returns true, that is) for when
dealing with sequences of more than one item.
Now there's only one more fish to fry, and that is the following: why is
(1 to 2) != 10 different then (1, 2) != 10. To tell you the truth, I
have no idea. Both left operands are a sequence of two items that (iirc)
after atomization is still a sequence of two items, of type xs:integer.
I tried another processor (altovaxml) to have a comparison against
Saxon. It returned the opposite of Saxon for all question marks below:
(10 to 10) != (10)
> true (?)
(10, 10) != (10)
> false
(10 to 10) != (10 to 10)
> false
(10 to 11) != (10)
> true
(10, 11) != (10)
> true
(1 to 2) != (10)
> false (?)
((1 to 2), (1 to 2)) != (10)
> true
(for $i in 1 to 2 return $i) != (10)
> false (?)
(for $i in 1 to 2 return xs:integer($i)) != (10)
> true
There's seems to be some logic involved that as soon as the 'to'
operator is used, the result is different than expected. Adding any cast
(xs:integer above, but any other will do) returns the expected 'true'.
Why is this cast necessary to get the same result as for normal
sequences as when using the 'to' operator?
Thanks Andrew, for the mind exercise, it was fun getting the grips
(almost) to some less-than-obvious stuff.
Note that the trick you mentioned, does not work, because the first part
(before '= false()') does not return a sequence of all false/true
values, it returns, as I see it, a sequence of one item.
((1 , 3) != 4) = false()
returns the opposite of
((1 , 3) != 4) = true()
for all tests above (replace (1, 3) with (1 to 3) to see the effect).
Cheers,
-- Abel Braaksma
http://www.nuntia.nl