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:

  • for-each
  • filter
  • fold-left
  • fold-right
  • for-each-pair

fn:for-each

for-each(1 to 5, function($a) { $a * $a })

fn:filter

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

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 for-each(1 to 10, $fMultiply)