<?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>29628</bug_id>
          
          <creation_ts>2016-05-15 19:08:55 +0000</creation_ts>
          <short_desc>16.2.1 fn:for-each - proposal of more succinct rules</short_desc>
          <delta_ts>2016-07-21 14:05:34 +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>Functions and Operators 3.1</component>
          <version>Candidate Recommendation</version>
          <rep_platform>PC</rep_platform>
          <op_sys>Windows NT</op_sys>
          <bug_status>CLOSED</bug_status>
          <resolution>WONTFIX</resolution>
          
          
          <bug_file_loc></bug_file_loc>
          <status_whiteboard></status_whiteboard>
          <keywords></keywords>
          <priority>P2</priority>
          <bug_severity>normal</bug_severity>
          <target_milestone>---</target_milestone>
          
          
          <everconfirmed>1</everconfirmed>
          <reporter name="Hans-Juergen Rennau">hrennau</reporter>
          <assigned_to name="Michael Kay">mike</assigned_to>
          <cc>abel.braaksma</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>126438</commentid>
    <comment_count>0</comment_count>
    <who name="Hans-Juergen Rennau">hrennau</who>
    <bug_when>2016-05-15 19:08:55 +0000</bug_when>
    <thetext>Would it not be simpler, clearer and more intuitive if the equivalent implementation were defined using the simple map operator:

declare function fn:for-each($seq, $f) {$seq ! $f(.)};

instead of:

declare function fn:for-each($seq, $f) {
  if (fn:empty($seq))
  then ()
  else ($f(fn:head($seq)), fn:for-each(fn:tail($seq), $f))
};</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>126443</commentid>
    <comment_count>1</comment_count>
    <who name="Abel Braaksma">abel.braaksma</who>
    <bug_when>2016-05-17 08:46:01 +0000</bug_when>
    <thetext>While I am not unsympathetic towards the proposed change, the original function shows the recursive nature and is a common way in functional languages to describe such higher order functions, this can be seen in many text books. 

Furthermore, I think it is good to show the tail-recursion, which is not present in the map operator (though it begs the question, is the current signature truly tail-recursive? I don&apos;t think so, as there is an embedded function call in the final fn:for-each call, a let-return statement would perhaps be better).</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>126476</commentid>
    <comment_count>2</comment_count>
    <who name="Michael Kay">mike</who>
    <bug_when>2016-05-22 21:11:46 +0000</bug_when>
    <thetext>I&apos;m a bit reluctant to define fn:for-each in terms of &quot;!&quot; because the current definition of &quot;!&quot; is itself very informal. Our normal approach is to define operators in terms of functions, rather than the other way around. We currently do this only for first-order operators such as &quot;+&quot; and &quot;=&quot;, but now we have higher-order functions it would make sense to define higher-order operators like &quot;!&quot; in terms of higher-order functions like fn:for-each.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>126480</commentid>
    <comment_count>3</comment_count>
    <who name="Michael Kay">mike</who>
    <bug_when>2016-05-23 11:55:46 +0000</bug_when>
    <thetext>In response to Abel&apos;s comment, there&apos;s no concept of tail recursion in the spec: whether a particular implementation recognizes this function body as tail recursive is purely an implementation matter.

(For Saxon, the rules are complex and not very consistent; a recursive call as the last item in an (X, Y, f()) construct is more likely to be recognized as a tail call in an XSLT template than in a function body).</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>126557</commentid>
    <comment_count>4</comment_count>
    <who name="Michael Kay">mike</who>
    <bug_when>2016-05-24 15:42:44 +0000</bug_when>
    <thetext>The WG decided that there was not a good case for making this change, both for the reasons outlined in comment 2, and because of timescales, and because of the risk of introducing new errors.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>126572</commentid>
    <comment_count>5</comment_count>
    <who name="Hans-Juergen Rennau">hrennau</who>
    <bug_when>2016-05-25 11:30:22 +0000</bug_when>
    <thetext>(In reply to Michael Kay from comment #2)
&gt; I&apos;m a bit reluctant to define fn:for-each in terms of &quot;!&quot; because the
&gt; current definition of &quot;!&quot; is itself very informal. Our normal approach is to
&gt; define operators in terms of functions, rather than the other way around. We
&gt; currently do this only for first-order operators such as &quot;+&quot; and &quot;=&quot;, but
&gt; now we have higher-order functions it would make sense to define
&gt; higher-order operators like &quot;!&quot; in terms of higher-order functions like
&gt; fn:for-each.

Of course I accept the decision not to take actions, for the reasons given.

But one remark in reply to the general approach of defining operators in terms of functions, and not the other way around, a remark which seemed to play a role in the decision.

I think the semantics of the map operator (!) and the path operator (/) cannot be defined in terms of an XQuery function, because the operator semantics involve a resetting of the inner focus. For these reasons, I think the map and the path operators are like &quot;semantic atoms&quot; (or axioms) and cannot be translated into the semantics of a function, and for this reason they might perhaps (?) legitimately be used in order to define the semantics of functions (like fn:for-each).</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>126573</commentid>
    <comment_count>6</comment_count>
    <who name="Michael Kay">mike</who>
    <bug_when>2016-05-25 14:13:03 +0000</bug_when>
    <thetext>&gt;I think the semantics of the map operator (!) and the path operator (/) cannot
be defined in terms of an XQuery function, because the operator semantics
involve a resetting of the inner focus.

You&apos;re right that this would need some new machinery, but it could be done if we really wanted to. For example one could use the approach of the XQuery 1.0 formal semantics which rewrites references to &quot;.&quot;, position() and last() in terms of variables. But rewriting &quot;!&quot; as a FLOWR expression is probably a better way of formalising the spec:

Then A!B ==&gt; 

let $last := count(A)
for $position in 1 to $last
let $dot := A[$position]
return B

But you have to be careful with these variables because of course there can be nested changes of focus, so it&apos;s certainly non-trivial.</thetext>
  </long_desc>
      
      

    </bug>

</bugzilla>