Higher-order Functions

Passing an inline function as parameter

xquery version "3.0";

declare namespace ex="http://exist-db.org/xquery/ex";

declare function ex:apply($func, $list) {
    for $item in $list return $func($item)
};

(: Create an inline function and assign it to $f2 :)
let $f2 := function($a) { upper-case($a) }
return
       ex:apply($f2, ("Hello", "world!"))
            

Using a named function reference

xquery version "3.0";

declare namespace ex="http://exist-db.org/xquery/ex";

declare function ex:apply($func as function(item()) as item()*, $list) {
    for $item in $list return $func($item)
};

(: Use function reference literal to find function at compile time :)
let $fApply := ex:apply#2
return
       $fApply(function($a) { upper-case($a) }, ("Hello", "world!"))
            

Using a dynamic function lookup

xquery version "3.0";

declare namespace ex="http://exist-db.org/xquery/ex2";

declare function ex:fold-left(
        $f as function(item()*, item()) as item()*, 
        $zero as item()*, 
        $seq as item()*) as item()* {
    if (fn:empty($seq)) then $zero
    else ex:fold-left($f, $f($zero, $seq[1]), subsequence($seq, 2))
};

(: Function reference is resolved dynamically at runtime :)
let $foldLeft := function-lookup(xs:QName("ex:fold-left"), 3)
return
    $foldLeft(function($a, $b) { $a * $b}, 1, 1 to 5)
            

Basic higher-order functions

The default function library provides a number of basic functions which take function items as arguments:

fn:map

map(function($a) { $a * $a }, 1 to 5)
            

fn:filter

fn:filter(function($a) {$a mod 2 = 0}, 1 to 10)

Closures

Inline function using variable from local context

xquery version "3.0";

declare function local:apply($names as xs:string*, $f as function(xs:string) as xs:string) {
    for $name in $names
    return
        $f($name)
};

let $string := "Hello "
let $f := function($name as xs:string) {
    (: $string will be copied into the functions context :)
    $string || $name
}
return
    local:apply(("Hans", "Rudi"), $f)
            

Partial function application

When passing functions as arguments, it is often useful to be able to set certain fixed parameters when creating the function reference. XQuery 3.0 allows this using ? as an argument placeholder.

Multiply each item in a sequence with a base value

xquery version "3.0";
            
declare namespace ex="http://exist-db.org/xquery/ex";

declare function ex:multiply($base, $number) {
    $base * $number
};

let $fMultiply := ex:multiply(10, ?)
return
    map($fMultiply, 1 to 10)