An inline function, function($v as xs:double) as xs:double { $v * 2 } (types optional), is bound with let and called like a variable. Inline functions are closures that capture variables in scope, accept partial application with ?, and chain with the arrow operator. Each expression below evaluates to 6:
xp 'let $f := (2, 3, 4) ! (let $a := . return function($n) { $a * $n }) return $f[2](2)' \
'let $plus := function($x, $y) { $x + $y } return $plus(2, ?)(4)' \
'let $s := function($n, $f) {if ($n) then $n + $f($n - 1, $f) else 0} return $s(3, $s)'Output
let $f := (2, 3, 4) ! (let $a := . return function($n) { $a * $n }) return $f[2](2) => 6
let $plus := function($x, $y) { $x + $y } return $plus(2, ?)(4) => 6
let $s := function($n, $f) {if ($n) then $n + $f($n - 1, $f) else 0} return $s(3, $s) => 6An inline function cannot see its own let variable, so recursion passes the function to itself. Type that parameter as function(*); the bare function() some references print is a syntax error (XPST0003). Named libraries belong in XQuery's declare function (XQuery 3.1 FLWOR Expressions) or XSLT's xsl:function.
Custom Functions
Custom functions are represented as function items (of type function(*)), a capability introduced in XPath 3.0 and extended in XPath 3.1 (e.g. the arrow operator => used in example 10 below). Each of the following expressions demonstrates a different function-related technique, but every one evaluates to the same result, 6:| let $f := function ($v) {$v * 2} return $f(3) | a simple function |
|
let $process := function($v as xs:double, $f as function(xs:double) as xs:double) as xs:double {$f($v)}, $mult2 := function ($n as xs:double) as xs:double {$n*2} return $process(3,$mult2) | passing a function to a function |
|
let $compose := function($f as function(xs:double) as xs:double, $g as function(xs:double) as xs:double) as function(xs:double) as xs:double {function ($x as xs:double) {$g($f($x))}}, $mult2 := function($x as xs:double) {$x*2}, $mult3 := function($x as xs:double) {$x*3} return $compose($mult2,$mult3)(1) | functions composition |
|
let $plus := function($x as xs:integer, $y as xs:integer) as xs:integer {$x+$y} return $plus(?,?)(2,4) | partial function application |
|
let $plus := function ($m as xs:integer) as (function(xs:integer) as xs:integer) {function ($n as xs:integer) {$m + $n}} return $plus(2)(4) | function closure |
|
let $s := function ($n as xs:integer, $f as function(xs:integer, function()) as xs:integer) as xs:integer {if ($n<1) then 0 else $n+$f($n - 1,$f)}, $sum := function($n as xs:integer) {$s($n,$s)} return $sum(3) | recursive function (not supported by all processors) |
| function($a as xs:double, $b as xs:double) as xs:double { $a * $b }(2,3) | inline function expression |
| let $f := (function($n){$n*2},function($n){$n*3}) return $f[2](2) | dynamic function call without reference by name |
| let $f := (2,3,4) ! (let $a := . return function($n) { $a * $n}) return $f[2](2) | collection of functions mapped from a collection (the bang operator ! can be used with nodes and built-in functions too) |
| let $p2 := function ($n){$n + 2}, $mult := function ($n,$f){$n*$f} return 1 => $p2() => $mult(2) | chaining of arrow functions (usable with built-in functions too) |
merged-01-01-ch03-custom-functions.xpath.txt
let $f := function ($v) {$v * 2}
return $f(3)
Output
6