Re: 99 bottles of beer
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).
PURCHASE STYLUS STUDIO ONLINE TODAY!
Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!
Download The World's Best XML IDE!
Accelerate XML development with our award-winning XML IDE - Download a free trial today!
Subscribe in XML format