This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.
Although the spec is probably technically correct, it would be worth some explanation of how function coercion interacts with maps and arrays. Firstly, if the expected type is a map or array type, then function coercion does not apply. That's because the expected type is not [written as a] TypedFunctionTest (bullet 3 of 3.1.5.2). Note that the bullets here are rather varied in style, for example: "If the expected type calls for a single item or optional single item" "If the expected type is xs:string or xs:string?" "If the expected type is a sequence of a generalized atomic type" It would be better if they were all phrased in terms of how the type is expressed syntactically. Secondly, if the expected type is (expressed as) a TypedFunctionTest, and the actual supplied value is a map or array, then function coercion does apply. For example, fn:sort expects a function item of type function(item()) as xs:anyAtomicType*, and it is acceptable to supply a map as the value of this argument. If a map $M is passed, the rules of function coercion say that this is equivalent to passing the function function($key as item()) as xs:anyAtomicType* { $M($key) } which in general (unless there is an atomization failure) will work; the sort key for any value not present in the map is an empty sequence. It's certainly worth a note or an example to explain this. Thirdly, if the expected type is written as function(*), then it is legal to supply a map or array as the value of the argument, but no coercion takes place.
I need to rewrite this as a result of 21893. I will see what can be made clearer when I do that rewrite.
It appears that no changes have been made to the spec in response to this issue.
To be resolved editorially.
An example of function coercion against a map item to include in the spec: let $m := map { "Monday" : true(), "Wednesday" : true(), "Friday" : true(), "Saturday" : false(), "Sunday" : false() } let $days := ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday") return fn:filter($days,$m) The map $m has a function signature of function(xs:anyAtomicType) as item()*. When the fn:filter() function is called, the following occurs to the fun\ ction: 1. The map $m is treated as function ($f) equivalent to map:get($m,?). 2. The function conversion rules result in applying function coercion to $f, wrapping $f in a new function ($p) with the signature function(item()) as\ xs:boolean. 3. $p is matched against the SequenceType of function(item()) as xs:boolean, and succeeds. 4. When $p is invoked by fn:filter(), function conversion and SequenceType matching rules are applied to the argument, resulting in an item() value ($\ a) or a type error. 5. $f is invoked with $a, which returns an xs:boolean or the empty sequence. 6. $p applies function conversion rules and SequenceType matching to the result sequence from $f. When the result is an xs:boolean the SequenceType ma\ tching succeeds. When it is an empty sequence (such as when $m does not contain a key for "Tuesday"), SequenceType matching results in a type error.
(In reply to John Snelson from comment #4) > An example of function coercion against a map item to include in the spec: > > let $m := map { > "Monday" : true(), > "Wednesday" : true(), > "Friday" : true(), > "Saturday" : false(), > "Sunday" : false() > } > let $days := ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", > "Saturday", "Sunday") > return fn:filter($days,$m) This returns: [XPTY0004] xs:boolean expected, empty sequence found. I would also like an example that filters, so I plan to provide both the example above and this one: let $m := map { "Monday" : true(), "Tuesday" : false(), "Wednesday" : true(), "Thursday" : false(), "Friday" : true(), "Saturday" : false(), "Sunday" : false() } let $days := ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday") return fn:filter($days,$m) => Monday Wednesday Friday
I started adding this to the spec, but had some concerns with parts of this as I went. (In reply to Michael Kay from comment #0) > Although the spec is probably technically correct, it would be worth some > explanation of how function coercion interacts with maps and arrays. > > Firstly, if the expected type is a map or array type, then function coercion > does not apply. That's because the expected type is not [written as a] > TypedFunctionTest (bullet 3 of 3.1.5.2). I assume that does not need to be stated explicitly, since lots of other things aren't TypedFunctionTest. > Note that the bullets here are > rather varied in style, for example: > > "If the expected type calls for a single item or optional single item" > "If the expected type is xs:string or xs:string?" > "If the expected type is a sequence of a generalized atomic type" > > It would be better if they were all phrased in terms of how the type is > expressed syntactically. Do you mean by adding a phrase like "written as a"? Or were you asking for something else? > Secondly, if the expected type is (expressed as) a TypedFunctionTest, and > the actual supplied value is a map or array, then function coercion does > apply. For example, fn:sort expects a function item of type function(item()) > as xs:anyAtomicType*, and it is acceptable to supply a map as the value of > this argument. I think you're simply pointing out that arrays and maps are functions? If so, it may be worth mentioning in a NOTE, e.g. * If the expected type is a TypedFunctionTest (possibly with an occurrence indicator *, +, or ?), function coercion is applied to each function in the given value. NOTE: Maps and arrays are functions, so function coercion applies to them as well. > If a map $M is passed, the rules of function coercion say > that this is equivalent to passing the function > > function($key as item()) as xs:anyAtomicType* { > $M($key) > } > > which in general (unless there is an atomization failure) will work; the > sort key for any value not present in the map is an empty sequence. > > It's certainly worth a note or an example to explain this. I would probably use the NOTE I suggested above, and add an example in the section on function coercion. > Thirdly, if the expected type is written as function(*), then it is legal to > supply a map or array as the value of the argument, but no coercion takes > place. I think this is covered by the above NOTE, and should also be covered in the example.