saxonica.com

saxon:function()

saxon:function($arg1 as xs:string, $arg2 as xs:integer) ==> function()

This function is available only in Saxon-PE and Saxon-EE

From Saxon 9.2, provided XQuery 1.1 support is enabled and the query prolog specifies version "1.1", the syntax my:function#3 can be used in place of the call saxon:function('my:function', 3). The implementation (with either syntax) has also been extended so that it works with all functions, not only with user-written functions.

This function takes as its arguments the name and arity of a function, 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 (this function is always evaluated at compile time). The first argument gives the name of the function as a lexical QName (using the default function namespace if unprefixed), the second gives the function arity (number of arguments).

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', 2), 0)"/>
</xsl:function>

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

Here is the same example in XQuery (using XQuery 1.1 syntax):

xquery version "1.1";
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, f:plus#2, 0)
};

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

The result of f:sum(1 to 4) is 10, while the result of f:product(1 to 4) is 24.

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

The type of the result of saxon:function is function(), a new type introduced in XQuery 1.1 - it is a third subtype of item() alongside nodes and atomic values.

Next