Changes

Jump to navigation Jump to search
m
Text replacement - "<syntaxhighlight lang="xquery">" to "<pre lang='xquery'>"
This [[Module Library|XQuery Module]] adds some useful higher-order functions, additional to the [[Higher-Order Functions]] provided by the official specification. All functions are introduced with the <code>hof:</code> prefix, which is linked to the statically declared <code>http://basex.org/modules/hof</code> namespace.
=Functions=With {{Announce|Version 11}}, many functions have been removed in favor of new features of XQuery 4:
==hof:id==
{|
|-valign="top"| width='90' 'BaseX 10'''| '''SignaturesXQuery 4'''|- valign="top"| {{Code|hof:drop-while}}| [https://qt4cg.org/specifications/xpath-functions-40/Overview.html#func-drop-while <code><b>hoffn:id</b>($expr as item()*) as item()*items-starting-where</code>]|-valign="top"| '''Summary'''{{Code|hof:id}}|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-identity <code>fn:identity</code>]|-valign="top"| '''Examples'''{{Code|hof:until}}|* <code>hof[https:id(1 to 5)</code> returns /qt4cg.org/specifications/xpath-functions-40/Overview.html#func-iterate-while <code>1 2 3 4 5fn:iterate-while</code>]* With higher|-order functions:<pre classvalign="brush:xquerytop">let $sort-by := function($f, $seq) | {{ for $x in $seq order by $f($x) return $x }let $sort := $sort-by(Code|hof:id#1, ?), $reversetake-sort := $sort-by(function($x) { -$x while}}, ?)return ( $sort((1, 5, 3, 2, 4)), '|', $reverse[https://qt4cg.org/specifications/xpath-functions-sort((1, 5, 3, 2, 4)))<40/pre>returns: Overview.html#func-take-while <code>1 2 3 4 5 | 5 4 3 2 1fn:items-before</code>]
|}
==hof:const=Conventions={||-| width='90' | '''Signatures'''|All functions in this module are assigned to the <code><bnowiki>hofhttp:const</b>($expr as item()*, $ignored as item()*) as item()*</code>|-| '''Summary'''|Returns its first argument unchanged and irgores 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 onebasex.|-| '''Examples'''|* <code>hof:const(42, 1337)<org/code> returns <code>42<modules/code>.* With higher-order functions:<pre class="brush:xquery">let $zip-sum := function($f, $seq1, $seq2) { sum(map-pairs($f, $seq1, $seq2)) }let $sum-all := $zip-sum(function($a, $b) { $a + $b }, ?, ?), $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 5))</prenowiki>* Another use-case: When inserting a key into a map, <code>$f</code> descides how namespace, which is statically bound to combine the new value with a possibly existing old one. <code>hof:const</code> here means ignoring the old value, so that's normal insertion.<pre class="brush:xquery">let $insert-with := function($f, $map, $k, $v) { let $old := $map($k), $new := if($old) then $f($v, $old) else $v return map:new(($map, map{ $k := $new Code|hof})) }let $map := map{ 'foo' := 1 }let $add := $insert-with(function($a, $b) {$a + $b}, ?, ?, ?), $insert := $insert-with(hof:const#2, ?, ?, ?)return ( $add($map, 'foo', 2)('foo'), $insert($map, 'foo', 42)('foo'))prefix.<br/pre>returns <code>3 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.|-| '''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, $acc, $action) { if(empty($input)) then $acc else ( $start</code> until the predicate <code>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==
{{Mark|Introduced with Version 7.2:}} {|width='100%'|-valign="top"| width='90120' | '''SignaturesSignature'''|<code><bpre>hof:top-k-by</b>( $seq input as item()*, $sort-key as function(item()) as item(), $k as xs:integer) 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>
|-| '''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)</code> }} returns <code>{{Code|1000 999 998 997 996</code>}}* <code>{{Code|hof:top-k-by(1 to 1000, function($x) { -$x }, 3)</code> }} returns <code>{{Code|1 2 3</code>}}* <code>hof:top-k-by(<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='120' | '''Signature'''|<pre>hof:top-k-with( $input as item()*, $comparator as function(item(), item()) as xs:boolean, $k as xs:integer) as item()*</pre>|- valign="top"| '''Summary'''|Returns the {{Code|$k}} items in {{Code|$input}} that are greatest when sorted in the order of the ''less-than'' predicate {{Code|$comparator}}. The function is a general version of {{Function||hof:top-k-by}}.|- valign="top"| '''Examples'''|* {{Code|hof:top-k-with(1 to 1000, function($a, $b) { $a lt $b }, 5)}} returns {{Code|1000 999 998 997 996}}* {Mark{Code|Introduced hof:top-k-with Version 7.(-5 to 5, function($a, $b) { abs($a) gt abs($b) }, 5)}} returns {{Code|0 1 -1 2 -2:}}|} =Identity= ==hof:const==
{|width='100%'|-valign="top"| width='90120' | '''SignaturesSignature'''|<code><bpre>hof:top-k-with</b>const( $seq input as item()*, $lt ignore as function(item(), item()) as xs:boolean, $k as xs:integer*) as item()*</codepre>|-valign="top"
| '''Summary'''
|Returns its first argument unchanged and ignores the <code>$k</code> items in <code>$seq</code> that are greatest when sorted in the order of the ''less-than'' predicate <code>$lt</code>second. The This function is a general version of <code>hof:topisn’t useful on its own, but can be used as argument to other higher-k-by($seqorder functions, $sort-keye.g., $k)</code>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-withpair(1 to 1000$seq1, $seq2, $f))}let $sum-all := $zip-sum(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 5))</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(-5 to 5, function($a, $b) { abs($a) gt abs(+ $b) }, 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}}
|}
=Changelog=
===;Version 711.2===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: [[#hof:top-k-by{{Function|hof:top-k-by]], [[#hof:top-k-with|hof:top-kdrop-with]]* Removed: [[#hof:iterate|hof:iterate]]while}}
===;Version 78.0===1* Added: {{Function||hof:scan-left}}, {{Function||hof:take-while}}
;Version 7.2
* Added: {{Function||hof:top-k-by}}, {{Function||hof:top-k-with}}
* Removed: hof:iterate
 
;Version 7.0
* module added
 
[[Category:XQuery]]
Bureaucrats, editor, reviewer, Administrators
13,554

edits

Navigation menu