The specification of fs:convert-operand() is inconsistent in the XQuery Formal Semantics Recommendation. Section 4.5.2, Paragraph "Normalization" says: `The internal function fs:convert-operand is applied to each pair of atomic values. If the first argument to this function has type xs:untypedAtomic, then the first argument is cast to type of the second argument.' Section 7.1.1, "The fs:convert-operand function", in contrast, says: `If $actual is an instance of type xs:untypedAtomic, then [...] if $expected is of numeric type, returns $actual cast to xs:double.' Note that (for e of type xs:untypedAtomic) e = 1 would be interpreted as an integer comparison according to the first definition of fs:convert-operand(), but as a double comparison according to the second.
I agree that there is an inconsistency. I believe the definition in 7.1.1 is correct (i.e., it agrees with XQuery section 3.5.2), so the text in 4.5.2 needs to be fixed. I propose to do so by being less specific in 4.5.2 about the workings of fs:convert-operand, since the reader can easily refer to 7.1.1 for the exact definition. Specifically, in 4.5.2 / Normalization, change: If the first argument to this function has type xs:untypedAtomic, then the first argument is cast to type of the second argument. If the second argument has type xs:untypedAtomic, the first argument is cast to a string. to: If either value is of type xs:untypedAtomic, this function casts it to a type determined by the other value. I believe this would be an editorial change, so I've downgraded this bug's Severity to "minor".
This issue has been entered as FS erratum E055, and the fix has been committed to the source files for the next edition of the FS document. Consequently, I'm marking this issue resolved-FIXED. If you agree with this resolution, please CLOSE the issue.
(Sorry for my late response. Somehow I missed your comment a year ago.) I'm not sure whether the proposed change actually makes things better. Note that that very specific sentence is about fs:convert-operand(), not the general comparison. More specifically, fs:convert-operand() will only cast its first argument (if necessary, and as determined by the second argument). Your sentence suggests that "either value" is cast to something, which is not what fs:convert-operand() does. A possible fix to your sentence could be If either value is of type xs:untypedAtomic, this function casts the first argument to a type determined by the second argument. I could also imagine something less specific, like This function ensures compatible types if either input to the general comparison was an instance of xs:untypedAtomic or a node.
(In reply to comment #3) > > I'm not sure whether the proposed change actually makes things better. > Note that that very specific sentence is about fs:convert-operand(), not > the general comparison. > > More specifically, fs:convert-operand() will only cast its first argument > (if necessary, and as determined by the second argument). Your sentence > suggests that "either value" is cast to something, which is not what > fs:convert-operand() does. Actually, I was trying to make the text *not* be about the inner workings of fs:convert-operand, just the net result of the two calls to it. That is, the interpretation I was hoping for was something like: The internal function fs:convert-operand is called twice for each pair of atomic values, and if either of the two values is of type xs:untypedAtomic, one of the calls will cast it to a type determined by the other value. That is, I want the idea of "two values" or "a pair of values" to mean the values bound to $v1 and $v2 within any given iteration of the inner 'some' expr and not the arguments to any given invocation of fs:convert-operand But, I agree, I haven't completely achieved that yet. So I think I need to slightly widen the scope of the change. How about this for the para: The normalization rule for a general comparison expression first atomizes each argument by applying fn:data, <NEW> resulting in two sequences of atomic values. Two nested <code>some</code> expressions then examine (potentially) every pair of values (one value from each sequence). For each pair, the internal function fs:convert-operand is called twice; if either of the two values is of type xs:untypedAtomic, one of the calls will cast it to a type determined by the other value. </NEW> The overloaded internal function corresponding to the general comparison operator is then applied to the two converted values.
Michael, looks much better now, thanks. I agree with your proposal, feel free to close the bug.
Ah good. I have updated the FS Errata document and the source files for the next edition of the FS document, and will now close the bug.