saxon:function($arg1 as xs:string, $arg2 as xs:integer) ==> function()
This function is available only in Saxon-PE and Saxon-EE
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.