Saxonica.com

saxon:function()

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

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 (this function is always evaluated at compile time).

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:

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)
};

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-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.

Next