This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.
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)) };
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).
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.
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).
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.
(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).
>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.