<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE bugzilla SYSTEM "https://www.w3.org/Bugs/Public/page.cgi?id=bugzilla.dtd">

<bugzilla version="5.0.4"
          urlbase="https://www.w3.org/Bugs/Public/"
          
          maintainer="sysbot+bugzilla@w3.org"
>

    <bug>
          <bug_id>27059</bug_id>
          
          <creation_ts>2014-10-15 14:57:31 +0000</creation_ts>
          <short_desc>[xp3.1] Function coercion, maps and arrays</short_desc>
          <delta_ts>2015-10-06 15:30:16 +0000</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>1</classification_id>
          <classification>Unclassified</classification>
          <product>XPath / XQuery / XSLT</product>
          <component>XPath 3.1</component>
          <version>Working drafts</version>
          <rep_platform>PC</rep_platform>
          <op_sys>All</op_sys>
          <bug_status>RESOLVED</bug_status>
          <resolution>FIXED</resolution>
          
          <see_also>https://www.w3.org/Bugs/Public/show_bug.cgi?id=21893</see_also>
          <bug_file_loc></bug_file_loc>
          <status_whiteboard></status_whiteboard>
          <keywords></keywords>
          <priority>P2</priority>
          <bug_severity>minor</bug_severity>
          <target_milestone>---</target_milestone>
          
          
          <everconfirmed>1</everconfirmed>
          <reporter name="Michael Kay">mike</reporter>
          <assigned_to name="Jonathan Robie">jonathan.robie</assigned_to>
          <cc>john.snelson</cc>
          
          <qa_contact name="Mailing list for public feedback on specs from XSL and XML Query WGs">public-qt-comments</qa_contact>

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>113208</commentid>
    <comment_count>0</comment_count>
    <who name="Michael Kay">mike</who>
    <bug_when>2014-10-15 14:57:31 +0000</bug_when>
    <thetext>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&apos;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:

&quot;If the expected type calls for a single item or optional single item&quot;
&quot;If the expected type is xs:string or xs:string?&quot;
&quot;If the expected type is a sequence of a generalized atomic type&quot;

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&apos;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.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>114179</commentid>
    <comment_count>1</comment_count>
    <who name="Jonathan Robie">jonathan.robie</who>
    <bug_when>2014-10-28 19:49:22 +0000</bug_when>
    <thetext>I need to rewrite this as a result of 21893. I will see what can be made clearer when I do that rewrite.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>121773</commentid>
    <comment_count>2</comment_count>
    <who name="Michael Kay">mike</who>
    <bug_when>2015-07-06 08:38:39 +0000</bug_when>
    <thetext>It appears that no changes have been made to the spec in response to this issue.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>122165</commentid>
    <comment_count>3</comment_count>
    <who name="John Snelson">john.snelson</who>
    <bug_when>2015-07-16 19:54:43 +0000</bug_when>
    <thetext>To be resolved editorially.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>122166</commentid>
    <comment_count>4</comment_count>
    <who name="John Snelson">john.snelson</who>
    <bug_when>2015-07-16 20:32:29 +0000</bug_when>
    <thetext>An example of function coercion against a map item to include in the spec:

let $m := map {
  &quot;Monday&quot; : true(),
  &quot;Wednesday&quot; : true(),
  &quot;Friday&quot; : true(),
  &quot;Saturday&quot; : false(),
  &quot;Sunday&quot; : false()
}
let $days := (&quot;Monday&quot;, &quot;Tuesday&quot;, &quot;Wednesday&quot;, &quot;Thursday&quot;, &quot;Friday&quot;, &quot;Saturday&quot;, &quot;Sunday&quot;)
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 &quot;Tuesday&quot;), SequenceType matching results in a type error.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>122167</commentid>
    <comment_count>5</comment_count>
    <who name="Jonathan Robie">jonathan.robie</who>
    <bug_when>2015-07-16 20:42:51 +0000</bug_when>
    <thetext>(In reply to John Snelson from comment #4)
&gt; An example of function coercion against a map item to include in the spec:
&gt; 
&gt; let $m := map {
&gt;   &quot;Monday&quot; : true(),
&gt;   &quot;Wednesday&quot; : true(),
&gt;   &quot;Friday&quot; : true(),
&gt;   &quot;Saturday&quot; : false(),
&gt;   &quot;Sunday&quot; : false()
&gt; }
&gt; let $days := (&quot;Monday&quot;, &quot;Tuesday&quot;, &quot;Wednesday&quot;, &quot;Thursday&quot;, &quot;Friday&quot;,
&gt; &quot;Saturday&quot;, &quot;Sunday&quot;)
&gt; 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 {
&quot;Monday&quot; : true(),
&quot;Tuesday&quot; : false(),
&quot;Wednesday&quot; : true(),
&quot;Thursday&quot; : false(),
&quot;Friday&quot; : true(),
&quot;Saturday&quot; : false(),
&quot;Sunday&quot; : false()
}
let $days := (&quot;Monday&quot;, &quot;Tuesday&quot;, &quot;Wednesday&quot;, &quot;Thursday&quot;, &quot;Friday&quot;, &quot;Saturday&quot;, &quot;Sunday&quot;)
return fn:filter($days,$m)

=&gt; 

Monday
Wednesday
Friday</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>123523</commentid>
    <comment_count>6</comment_count>
    <who name="Jonathan Robie">jonathan.robie</who>
    <bug_when>2015-10-06 15:30:16 +0000</bug_when>
    <thetext>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)
&gt; Although the spec is probably technically correct, it would be worth some
&gt; explanation of how function coercion interacts with maps and arrays.
&gt; 
&gt; Firstly, if the expected type is a map or array type, then function coercion
&gt; does not apply. That&apos;s because the expected type is not [written as a]
&gt; TypedFunctionTest (bullet 3 of 3.1.5.2). 

I assume that does not need to be stated explicitly, since lots of other things aren&apos;t TypedFunctionTest.

&gt; Note that the bullets here are
&gt; rather varied in style, for example:
&gt; 
&gt; &quot;If the expected type calls for a single item or optional single item&quot;
&gt; &quot;If the expected type is xs:string or xs:string?&quot;
&gt; &quot;If the expected type is a sequence of a generalized atomic type&quot;
&gt; 
&gt; It would be better if they were all phrased in terms of how the type is
&gt; expressed syntactically.

Do you mean by adding a phrase like &quot;written as a&quot;? Or were you asking for something else?

&gt; Secondly, if the expected type is (expressed as) a TypedFunctionTest, and
&gt; the actual supplied value is a map or array, then function coercion does
&gt; apply. For example, fn:sort expects a function item of type function(item())
&gt; as xs:anyAtomicType*, and it is acceptable to supply a map as the value of
&gt; this argument. 

I think you&apos;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.


&gt; If a map $M is passed, the rules of function coercion say
&gt; that this is equivalent to passing the function
&gt; 
&gt; function($key as item()) as xs:anyAtomicType* {
&gt;   $M($key)
&gt; }
&gt; 
&gt; which in general (unless there is an atomization failure) will work; the
&gt; sort key for any value not present in the map is an empty sequence.
&gt; 
&gt; It&apos;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.

&gt; Thirdly, if the expected type is written as function(*), then it is legal to
&gt; supply a map or array as the value of the argument, but no coercion takes
&gt; place.

I think this is covered by the above NOTE, and should also be covered in the example.</thetext>
  </long_desc>
      
      

    </bug>

</bugzilla>