Next: , Up: Higher-Order Functions   [Contents]

1.1 Partial Application

function: item()+ f:partial (fnref as item()+, args as item()*)


Partially apply dynamic function reference fnref

When provided to f:apply, fnref will be applied with args as its beginning argments, followed by any arguments to ‘f:apply’.

Note that you usually do not have to invoke this function directly: the dynamic function calls will handle currying/partial application for you, which has a much more inviting syntax.

Partially applied functions may continue to be partially applied until their parameters are exhausted. This can be used to implement currying.

When destructuring the result of this function, note that the returned function reference may not match fnref by reference, as it may have been modified.


<function name="f:partial"  as="item()+">
  <param name="fnref"  as="item()+" />
  <param name="args"  as="item()*" />

  <!-- note that, if FNREF is partially applied, then this arity
       represents the arity of the partially applied function, _not_
       the target function -->
  <variable name="arity"  as="xs:integer"  select="f:arity( $fnref )" />

  <variable name="argn"  as="xs:integer"  select="count( $args )" />

    <when test="$argn gt $arity">
      <apply-templates mode="f:partial-arity-error-hook"  select="$fnref">
        <with-param name="fnref"  select="$fnref" />
        <with-param name="args"  select="$args" />

      <variable name="new-ref"  select="f:push-args( $fnref, $args )" />

      <sequence select="if ( $argn eq $arity ) then _f:apply-partial( $new-ref ) else $new-ref" />
function: xs:boolean f:is-partial (fnref as item()+)


Determines whether FNREF is a partial application

You really should not rely on this for your code—it is intended for internal use. Instead, treat partial applications opaquely as their own functions.


<function name="f:is-partial"  as="xs:boolean">
  <param name="fnref"  as="item()+" />

  <!-- if we're passed a sequence, then the function portion of the
       reference is first; all others are arguments -->
  <variable name="fn"  select="$fnref[ 1 ]" />

  <!-- we never want to fail, so we perform our type check here rather
       than using param/@as -->
  <sequence select="$fn instance of element(f:ref) and exists( $fnref[ 2 ] )" />
match: f:partial-arity-error-hook on f:ref

Hook invoked when the number of arguments of a partial application exceeds the parameter count of the target function

The ‘target’ function is the root of the partial application—given Fx → F'y → F''z, F is the target.

Implementations may override this hook to display their own errors, or even handle the error and continue by returning a proper partial application. For such implementation details, see apply/partial.xsl.

<template mode="f:partial-arity-error-hook"  match="f:ref"  priority="1">
  <param name="args"  as="item()*" />

  <variable name="arity"  as="xs:integer"  select="f:arity(.)" />
  <variable name="argn"  as="xs:decimal"  select="count( $args )" />

  <sequence select="error( QName( namespace-uri-for-prefix( 'f', . ), 'err:PARTIAL_PARAM_OVERFLOW' ), concat( 'Attempted partial application of ', 'function of arity ', $arity, ' with ', $argn, ' arguments' ) )" />
function: xs:sequence* _f:apply-partial (fnref as item()+)


Apply a partial dynamic function application

This function is called automatically by f:partial when partial application would otherwise result in the returning of a nullary function. It performs no validations to ensure the integrity of the data.

Just as f:apply, please note that up to eight arguments are supported. This should be enough.


<function name="_f:apply-partial">
  <param name="fnref"  as="item()+" />

  <variable name="args"  select="f:args( $fnref )" />

  <variable name="desc"  as="element( f:ref )"  select="$fnref[ 1 ]" />

  <!-- just as `f:apply', we support up to 8 arguments -->
  <apply-templates select="$desc"  mode="f:apply">
    <with-param name="arg1"  select="$args[ 1 ]" />
    <with-param name="arg2"  select="$args[ 2 ]" />
    <with-param name="arg3"  select="$args[ 3 ]" />
    <with-param name="arg4"  select="$args[ 4 ]" />
    <with-param name="arg5"  select="$args[ 5 ]" />
    <with-param name="arg6"  select="$args[ 6 ]" />
    <with-param name="arg7"  select="$args[ 7 ]" />
    <with-param name="arg8"  select="$args[ 8 ]" />

Next: , Up: Higher-Order Functions   [Contents]