Higher-Order Functions

Higher-Order Functions in XPath

Functions are items: substring#2 names the two-argument substring() without calling it, concat(?, ".", ?) is a partial application with two holes, and function-lookup() finds a function by name and arity at run time (or returns (), a portable way to probe a processor). function-name() and function-arity() inspect them, and for-each(), filter(), fold-left(), fold-right(), for-each-pair(), sort() and apply() take them:

Function items, folds and partial application
xp 'function-lookup(xs:QName("fn:substring"), 2)("abcd", 2)' \
   'fold-left(//price, 0, function($sum, $p) { $sum + xs:decimal($p) })' \
   'fold-right(1 to 5, "***", concat(?, ".", ?))'
Output
function-lookup(xs:QName("fn:substring"), 2)("abcd", 2) => "bcd"
fold-left(//price, 0, function($sum, $p) { $sum + xs:decimal($p) }) => 134.74
fold-right(1 to 5, "***", concat(?, ".", ?)) => "1.2.3.4.5.***"

fold-left() sums exactly because the callback casts each price to xs:decimal; fold-right() works from the end, so the stars land last. Use ! for plain loops and these functions when the operation is a parameter.


Higher order Functions

Higher-order functions accept or return other functions — looking up a function by name and arity, inspecting a function item's name and arity, or applying a function across a sequence. See also Custom Functions for user-defined function items.
function-lookup(xs:QName("fn:substring"),2)("abcd",2)bcd
function-name(fn:substring#2)fn:substring
function-arity(fn:substring#3)3
for-each(1 to 5, function($a) { $a * $a })(1,4,9,16,25)
filter(1 to 10, function($a) {$a mod 2 = 0})(2,4,6,8,10)
fold-left(1 to 5, 10000, function($a, $b) { $a + $b })10015
fold-right(1 to 5, "***", fn:concat(?, ".", ?))1.2.3.4.5.***
for-each-pair(("a", "b", "c"), ("x", "y", "z"), concat#2)("ax","by","cz")

The notation fn:substring#2 refers to the 2-argument overload of fn:substring as a function item, without calling it; ? in an argument position (as in fn:concat(?, ".", ?)) leaves that argument unbound, producing a partially-applied function.

ch03-higher-order-functions.xpath.txt
merged-01-01-ch03-higher-order-functions.xpath.txt
for-each(1 to 5, function($a) { $a * $a })
Output
(1, 4, 9, 16, 25)