This module [[Module Library|XQuery Module]] adds some useful higher-order functions that were left out of the official spec. All functions are introduced with the <code>hof:</code> prefix, which is linked additional to the statically declared <code>http://basex.org/modules/hof</code> namespace[[Higher-Order Functions]] provided by the official specification.
=Functions=With {{Announce|Version 11}}, many functions have been removed in favor of new features of XQuery 4:
==hof:id==
{|
|-valign="top"| valign='top' width='90BaseX 10''' | '''SignaturesXQuery 4'''|- valign="top"| {{Code|hof:drop-while}}| [https://qt4cg.org/specifications/xpath-functions-40/Overview.html#func-drop-while <code>fn:items-starting-where<b/code>]|- valign="top"| {{Code|hof:id}}| [https://qt4cg.org/specifications/xpath-functions-40/Overview.html#func-identity </bcode>($expr as item()*) as item()*fn:identity</code>]|-| valign='"top' "| {{Code| '''Summary'''hof:until}}|Returns its argument unchanged[https://qt4cg. This function isn't useful on its own, but can be used as argument to other higherorg/specifications/xpath-order functions-40/Overview.html#func-iterate-while <code>fn:iterate-while</code>]|-| valign='"top' "| {{Code| '''Examples'''hof:take-while}}|* <code>hof[https:id(1 to 5)</code> returns /qt4cg.org/specifications/xpath-functions-40/Overview.html#func-take-while <code>1 2 3 4 5fn:items-before</code>]
|}
==hof:const=Conventions={||-| valign='top' width='90' | '''Signatures'''|All functions in this module are assigned to the <code><bnowiki>http://basex.org/modules/hof:const</bnowiki>($expr as item()*, $ignored as item()*) as item()*</code>|-| valign='top' | '''Summary'''|Returns its first argument unchanged and irgores the second. This function isn't useful on its ownnamespace, but can be used as argument which is statically bound to other higher-order functions.|-| valign='top' the {{Code| '''Examples'''|* <code>hof:const(42, 1337)}} prefix.<br/code> returns <code>42</code>.|}=Loops=
==hof:fold-left1==
{|width='100%'|-| valign='"top' "| width='90120' | '''SignaturesSignature'''|<code><bpre>hof:fold-left1</b>( $input as item()+, $f action as function(item()*, item()) as item()*, $seq as item()+) as item()*</codepre>|-| valign='"top' "| '''Summary'''|Works the same as [[Higher-Order_FunctionsOrder Functions#fn:fold-left($f, $seed, $seq)|fn:fold-left($f, $seed, $seq)]], but doesn't does not need a seed, because the sequence must be non-empty.|-| valign='"top' | '''Errors'''|''XPTY0004'' if <code>$seq</code> is empty|-"| valign='top' | '''Examples'''
|
* <code>{{Code|hof:fold-left1(1 to 10, function($a, $b) { $a + $b }, 1 to 10)</code> }} returns <code>{{Code|55</code>}}.* <code>{{Code|hof:fold-left1((), function($a, $b) { $a + $b }, ())</code> }} throws <code>{{Code|XPTY0004</code>}}, because <code>{{Code|$seq</code> }} has to be non-empty.
|}
==hof:untilscan-left== {|width='100%'|-| valign='"top' "| width='90120' | '''SignaturesSignature'''|<code><bpre>hof:until</b>scan-left( $pred input as functionitem()*, $zero as item()*) as xs:boolean, $f action as function(item()*) as , item()*, $start ) as item()*) as item()*</codepre>|-| valign='"top' "| '''Summary'''|Applies the This function <code>$f</code> is similar to [[Higher-Order Functions#fn:fold-left|fn:fold-left]], but it returns a list of successive reduced values from the initial value left. It is equivalent to:<codepre lang='xquery'>declare function hof:scan-left($input, $start</code> until the predicate <code>acc, $action) { if(empty($input)) then $acc else ( $acc, hof:scan-left(tail($input), $action($pred</code> applied to the result returns <code>trueacc, head($input)), $action) )};</codepre>.|-| valign='"top' "| '''Examples'''
|
* <code>hof:until(function($x) { $x ge 1000 }, function($y) { 2 * $y }, 1)</code> returns <code>1024</code>.* Calculating the square-root of a number by iteratively improving an initial guessReturns triangular numbers:<pre classlang="brush:'xquery"'>let $sqrt := function($x as xs:double) as xs:double { hof:untilscan-left( 1 to 10, 0, function($res) { abs($res * $res - $x) < 0.00001 }a, function($guessb) { ($guess a + $x div $guess) div 2 b }, $x )}return $sqrt(25)
</pre>
returns <code>5.000000000053722</code>.
|}
=Sorting=
==hof:top-k-by==
{|width='100%'|-| valign='"top' "| width='90120' | '''SignaturesSignature'''|<code><bpre>hof:top-k-by</b>( $input as item()*, $sort-key as function(item()) as item(), $k as xs:integer, $seq as item()*) as item()*</codepre>|-| valign='"top' "| '''Summary'''|Returns the <code>{{Code|$k</code> }} items in <code>{{Code|$seq</code> input}} that are greatest when sorted by the result of <code>{{Code|$f</code> key}} applied to the item. The function is a much more efficient implementation of the following scheme:<pre classlang="brush:'xquery"'>( for $x item in $seqinput order by $sort-key($xitem)descending return $xitem
)[position() <= $k]
</pre>
|-| valign='"top' | '''Errors'''|''XPTY0004'' if <code>$sort-key</code> doesn't return exactly one item|-"| valign='top' | '''Examples'''
|
* <code>{{Code|hof:top-k-by(1 to 1000, hof:id#1, 5, 1 to 1000)</code> }} returns <code>{{Code|1000 999 998 997 996</code>}}* <code>{{Code|hof:top-k-by(1 to 1000, function($x) { -$x }, 3, 1 to 1000)</code> }} returns <code>{{Code|1 2 3</code>}}* <code>hof:top-k-by(xs:integer#1, 2, <x a='1' b='2' c='3'/>/@*, xs:integer#1, 2)/node-name()</code> returns <code>{{Code|c b</code>}}
|}
==hof:top-k-with==
{|width='100%'|-| valign='"top' "| width='90120' | '''SignaturesSignature'''|<code><bpre>hof:top-k-with</b>( $input as item()*, $lt comparator as function(item()?, item()?) as xs:boolean, $k as xs:integer, $seq as item()*) as item()*</codepre>|-| valign='"top' "| '''Summary'''|Returns the <code>{{Code|$k</code> }} items in <code>{{Code|$seq</code> input}} that are greatest when sorted in the order of the ''less-than'' predicate <code>{{Code|$lt</code>comparator}}. The function is a general version of <code>{{Function||hof:top-k-by}}.|- valign="top"| '''Examples'''|* {{Code|hof:top-k-with(1 to 1000, function($sorta, $b) { $a lt $b }, 5)}} returns {{Code|1000 999 998 997 996}}* {{Code|hof:top-k-keywith(-5 to 5, function($ka, $b) { abs($a) gt abs($b) }, 5)}} returns {{Code|0 1 -1 2 -2}}|} =Identity= ==hof:const== {| width='100%'|- valign="top"| width='120' | '''Signature'''|<pre>hof:const( $input as item()*, $seqignore as item()*) as item()*</codepre>.|-valign="top"| '''Summary'''|Returns its first argument unchanged and ignores the second. This function isn’t useful on its own, but can be used as argument to other higher-order functions, e.g., when a function combining two values is expected and one only wants to retain the left one.| - valign='"top' "| '''Examples'''
|
* {{Code|hof:const(42, 1337)}} returns {{Code|42}}.* With higher-order functions:<codepre lang='xquery'>hoflet $zip-sum :top= function($f, $seq1, $seq2) { sum(for-keach-pair($seq1, $seq2, $f))}let $sum-all := $zip-withsum(function($a, $b) { $a lt + $b }, ?, ?)let $sum-left := $zip-sum(hof:const#2, ?, ?)return ( $sum-all((1, 1, 1, 1, 1), 1 to 5), $sum-left((1, 1, 1, 1, 1), 1 to 10005))</code> returns <code>1000 999 998 997 996</codepre>* Another use-case: When inserting a key into a map, {{Code|$f}} decides how to combine the new value with a possibly existing old one. {{Code|hof:const}} here means ignoring the old value, so that's normal insertion.<codepre lang='xquery'>hoflet $insert-with := function($f, $map, $k, $v) { let $old := $map($k) let $new := if($old) then $f($v, $old) else $v return map:merge(($map, map:top-entry($k, $new)))}let $map := map { 'foo': 1 }let $add := $insert-with(function($a, $b) { abs($a) gt abs(+ $b) }, 5?, ?, -5 to 5?)</code> returns <code>0 1 let $ins := $insert-1 with(hof:const#2 -, ?, ?, ?)return ( $add($map, 'foo', 2)('foo'), $ins($map, 'foo', 42)('foo'))</codepre>returns {{Code|3 42}}
|}
=Recent ChangesChangelog= ;Version 11.0* Removed: {{Code|hof:until}} (replaced with {{Code|fn:iterate-while}}, {{Code|hof:if}} (replaced with {{Code|fn:identity}}, {{Code|hof:drop-while}} (replaced with {{Code|fn:items-starting-where}}), {{Code|hof:take-while}} (replaced with {{Code|fn:items-before}}) ;Version 9.5* Added: {{Function||hof:drop-while}} ;Version 8.1* Added: {{Function||hof:scan-left}}, {{Function||hof:take-while}}
;Version 7.2* removed <code>hofAdded:iterate</code>* added <code>{{Function||hof:top-k-by</code> and <code>}}, {{Function||hof:top-k-with</code>}}* Removed: hof:iterate
[[Category:XQuery]];Version 7.0* module added