[xsl] W3C Specification of fn:filter() -- is this a bug in the document or in Saxon?

Subject: [xsl] W3C Specification of fn:filter() -- is this a bug in the document or in Saxon?
From: "Dimitre Novatchev dnovatchev@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Mon, 9 Sep 2019 00:17:23 -0000
The W3C F&O 3.1 spec (at
https://www.w3.org/TR/xpath-functions-31/#func-filter ) says:

Rules

The effect of the function is equivalent to the following implementation in
XQuery:

.  .  .  .  .  .  .  .  .

or its equivalent in XSLT:

<xsl:function name="fn:filter" as="item()*">
  <xsl:param name="seq" as="item()*"/>
  <xsl:param name="f" as="function(item()) as xs:boolean"/>
  <xsl:if test="fn:exists($seq)">
    <xsl:sequence select="fn:head($seq)[$f(.) eq fn:true()],
fn:filter(fn:tail($seq), $f)"/>
  </xsl:if>
</xsl:function>



The transformation below shows that fn:filter() is actually ***not***
equivalent to the above, specification-provided "XSLT - equivalent"
xsl:function:

<xsl:stylesheet  version="3.0" xmlns:xsl="
http://www.w3.org/1999/XSL/Transform";
  xmlns:xs="http://www.w3.org/2001/XMLSchema"; xmlns:f="some:f">
  <xsl:output method="text"/>

  <xsl:template name="xsl:initial-template">
    <xsl:sequence select="filter(1 to 10000, function($n){$n idiv 2 * 2 eq
$n})"/>
    =================
    <xsl:sequence select="f:filter(1 to 10000, function($n){$n idiv 2 * 2
eq $n})"/>
  </xsl:template>

  <xsl:function name="f:filter" as="item()*">
    <xsl:param name="seq" as="item()*"/>
    <xsl:param name="f" as="function(item()) as xs:boolean"/>
    <xsl:if test="exists($seq)">
      <xsl:sequence select="head($seq)[$f(.) eq true()],
f:filter(tail($seq), $f)"/>
    </xsl:if>
  </xsl:function>
</xsl:stylesheet>

When this transformation is executed, the call to the standard filter()
function produces the expected result as can be seen from the output.

However, the call to the "equivalent" xsl:function with exactly the same
arguments as provided in the call to the standard filter() function,
produces partial output and a stack-overflow exception is thrown.

Because "equivalent" means the two functions must produce the same result
for for all possible values in the same set of arguments, this example
proves that the two functions are not equivalent.

The question is:

1. Is the specification correct -- in which case this is a bug in Saxon and
the specification clearly assumes that an XSLT 3 processor must correctly
recognize and optimize tail-recursion ?

2. Or, is this a bug in the specification, meaning that no equivalent XSLT
implementation can be provided?


BTW, there is a pure XPath 3 expression that is truly equivalent to the
standard filter() function for all practical purposes.

Thus the specification is partially correct -- that an equivalent XSLT
implementation exists, but the specification fails to provide an example of
such equivalent XSLT implementation.

I have checked that the specification-provided "equivalent XQuery
implementation" also ends in StackOverflow exception when called with the
same arguments, so the same problem exists with that statement, too.

*Conclusion to myself*: It would have been better to avoid these problems
in the specification by providing a truly equivalent, single XPath 3
implementation, which of course can be used both in an XSLT and in an
XQuery implementations.

It seems that the document cannot be corrected as the respective WGs no
longer exist. Even if an activity to correct the spec is possible, I doubt
that the editors would be interested in providing this correction.

Nevertheless, the issue raised and the fact that a solution really exists
are still useful to anyone interested in understanding XPath 3, which
probably means everyone in this list.

*To put it short*: Whenever one sees a statement like "this is the
equivalent XSLT implementation" we must react with: "Hmm... not exactly so"

As used to say in the past -- just my 2c.   p

--
Cheers,
Dimitre Novatchev
---------------------------------------
Truly great madness cannot be achieved without significant intelligence.
---------------------------------------
To invent, you need a good imagination and a pile of junk
-------------------------------------
Never fight an inanimate object
-------------------------------------
To avoid situations in which you might make mistakes may be the
biggest mistake of all
------------------------------------
Quality means doing it right when no one is looking.
-------------------------------------
You've achieved success in your field when you don't know whether what
you're doing is work or play
-------------------------------------
To achieve the impossible dream, try going to sleep.
-------------------------------------
Facts do not cease to exist because they are ignored.
-------------------------------------
Typing monkeys will write all Shakespeare's works in 200yrs.Will they write
all patents, too? :)
-------------------------------------
Sanity is madness put to good use.
-------------------------------------
I finally figured out the only reason to be alive is to enjoy it.

Current Thread