This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 29628 - 16.2.1 fn:for-each - proposal of more succinct rules
Summary: 16.2.1 fn:for-each - proposal of more succinct rules
Status: CLOSED WONTFIX
Alias: None
Product: XPath / XQuery / XSLT
Classification: Unclassified
Component: Functions and Operators 3.1 (show other bugs)
Version: Candidate Recommendation
Hardware: PC Windows NT
: P2 normal
Target Milestone: ---
Assignee: Michael Kay
QA Contact: Mailing list for public feedback on specs from XSL and XML Query WGs
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-05-15 19:08 UTC by Hans-Juergen Rennau
Modified: 2016-07-21 14:05 UTC (History)
1 user (show)

See Also:


Attachments

Description Hans-Juergen Rennau 2016-05-15 19:08:55 UTC
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))
};
Comment 1 Abel Braaksma 2016-05-17 08:46:01 UTC
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'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).
Comment 2 Michael Kay 2016-05-22 21:11:46 UTC
I'm a bit reluctant to define fn:for-each in terms of "!" because the current definition of "!" 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 "+" and "=", but now we have higher-order functions it would make sense to define higher-order operators like "!" in terms of higher-order functions like fn:for-each.
Comment 3 Michael Kay 2016-05-23 11:55:46 UTC
In response to Abel's comment, there'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).
Comment 4 Michael Kay 2016-05-24 15:42:44 UTC
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.
Comment 5 Hans-Juergen Rennau 2016-05-25 11:30:22 UTC
(In reply to Michael Kay from comment #2)
> I'm a bit reluctant to define fn:for-each in terms of "!" because the
> current definition of "!" 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 "+" and "=", but
> now we have higher-order functions it would make sense to define
> higher-order operators like "!" in terms of higher-order functions like
> 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 "semantic atoms" (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).
Comment 6 Michael Kay 2016-05-25 14:13:03 UTC
>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'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 ".", position() and last() in terms of variables. But rewriting "!" as a FLOWR expression is probably a better way of formalising the spec:

Then A!B ==> 

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's certainly non-trivial.