# saxon:function()

function($arg1 as xs:string, $arg2 as xs:integer) ==> jt:net.sf.saxon.expr.UserFunction

This function is available only in Saxon-SA

This function takes as its arguments the name and arity of a user-defined function (a function declared using "declare function" in XQuery, or <xsl:function> in XSLT), and returns a value that represents the function and can be used to invoke the function using saxon:call. This allows higher-order functions to be implemented in XSLT and XQuery, that is, functions that take other functions as arguments. An example of such a higher-order function is saxon:for-each-group, which provides grouping capability in XQuery similar to that of the `xsl:for-each-group` instruction in XSLT.

The arguments must be specified as literals.

Here is an example, the textbook `fold` function in XSLT:

    <xsl:function name="f:fold">
      <xsl:param name="sequence"/>
      <xsl:param name="operation"/>
      <xsl:param name="start-value"/>
      <xsl:sequence select="if (empty($sequence))
                            then $start-value
                            else f:fold(remove($sequence, 1),
                                        $operation,
                                        saxon:call($operation, $start-value, $sequence[1])"/>
    </xsl:function>

    <xsl:function name="f:plus">
      <xsl:param name="a"/>
      <xsl:param name="b"/>
      <xsl:sequence select="$a + $b"/>
    </xsl:function>

    <xsl:function name="f:times">
      <xsl:param name="a"/>
      <xsl:param name="b"/>
      <xsl:sequence select="$a * $b"/>
    </xsl:function>

    <xsl:function name="f:sum">
      <xsl:param name="sequence"/>
      <xsl:sequence select="f:fold($sequence, saxon:function('f:plus'), 0)"/>
    </xsl:function>

    <xsl:function name="f:product">
      <xsl:param name="sequence"/>
      <xsl:sequence select="f:fold($sequence, saxon:function('f:times'), 0)"/>
    </xsl:function>

Here is the same example in XQuery:

    declare function f:fold ($sequence as xs:double*, $operation, $start-value as xs:double) {
         if (empty($sequence))
         then $start-value
         else f:fold(remove($sequence, 1),
                     $operation,
                     saxon:call($operation, $start-value, $sequence[1]))
    };

    declare function f:plus ($a as xs:double, $b as xs:double) {$a + $b};

    declare function f:times ($a as xs:double, $b as xs:double) {$a * $b};

    declare function f:sum ($sequence as xs:double*) as xs:double {
       f:fold($sequence, saxon:function('f:plus', 2), 0)
    };

    declare function f:product ($sequence as xs:double*) as xs:double {
       f:fold($sequence, saxon:function('f:times', 2), 1)
    };

    <p>The result of <code>f:sum(1 to 4)</code> is 10, while the result of <code>f:product(1 to 4)</code>
    is 24.</p>

Higher-order functions allow many generic functions such as `fold` to be written, and their availability in Saxon-SA turns XSLT and XQuery into fully-fledged functional programming languages.

The type of the result of saxon:function is `jt:net.sf.saxon.expr.UserFunctionCall`, where the prefix `jt` represents the URI `http://net.sf.saxon/java-type`.

Expand | Up Next