I have added this to the XSLT 3.0 test suite as test case higher-order-functions-068, and I confirm it is still failing with the current development build.

The hypothesis I am exploring is that it is an interaction between function closures and tail recursion; my suspicion is that when the stackframe is reused/overwritten for the purpose of tail-recursion, the values required for the function closure are being corrupted. It's all pretty complex!

Michael Kay
Saxonica

On 06/02/2013 03:14, Abel Braaksma wrote:
When I define the following continuation version of the Fibonacci sequence in XSLT 3:

    <xsl:function name="f:fib">
        <xsl:param name="n" as="xs:integer" />
        <xsl:param name="countfun" as="function(*)" />
       
        <xsl:sequence select="
            if ($n = 1 or $n = 2)
            then $countfun(1)
            else let $first :=
                     function($x as xs:integer) as function(*)
                     {
                        let $second := function($y as xs:integer) as function(*)
                        {
                            $countfun($x + $y)
                        }
                        return f:fib($n - 2, $second)
                     }
                 return f:fib($n - 1, $first)" />
    </xsl:function>

and I call it as follows:

<xsl:value-of select="f:fib(10, function($a as xs:integer){$a})" />

the expected result is 55. However, I receive the following error:

Engine name: Saxon-EE 9.4.0.4
Severity: fatal
Description: Required item type of second argument of anonymous function is function(); supplied value has item type xs:integer
Start location: 36:0
URL: http://www.w3.org/TR/xslt20/#err-XTTE0790

The function is inspired by this snippet http://fssnip.net/eU, though other functional languages have similar examples. The idea behind the excercise is to eliminate the double recursive exit point of the function by creating a continuation function.
However, either the error is confusing (I don't see any anonymous function call with a function argument) or something else is happening.

I also tried the fully typed version, and an untyped version. Here's the fully typed variant:

<xsl:function name="f:fib" as="xs:integer">
    <xsl:param name="n" as="xs:integer" />
    <xsl:param name="countfun" as="function(xs:integer) as xs:integer" />
   
    <xsl:sequence select="
        if ($n = 1 or $n = 2)
        then $countfun(1)
        else let $first :=
                 function($x as xs:integer) as xs:integer
                 {
                    let $second := function($y as xs:integer) as xs:integer
                    {
                        $countfun($x + $y)
                    }
                    return f:fib($n - 2, $second)
                 }
             return f:fib($n - 1, $first)" />
</xsl:function>


Any idea what I'm missing here, or is this perhaps an error with Saxon?

Thanks,
Abel




------------------------------------------------------------------------------
Free Next-Gen Firewall Hardware Offer
Buy your Sophos next-gen firewall before the end March 2013 
and get the hardware for free! Learn more.
http://p.sf.net/sfu/sophos-d2d-feb


_______________________________________________
saxon-help mailing list archived at http://saxon.markmail.org/
saxon-help@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/saxon-help