XQuery/高阶函数
您有一个项目序列,并且想要对序列中的每个项目执行一系列连续的操作。
您希望使用单个函数,并将一系列函数作为参数传递给该函数。
函数式语言是将函数视为一等数据类型的语言。它们通常有一个函数,允许您传递一个项目列表并告诉它对这些项目中的每一个执行什么函数。就像 XML 转换一样,当您需要对大量项目执行许多小型任务时,函数式语言是理想选择。函数式语言非常适合这些任务,因为实际执行函数的顺序并不需要保证。开发人员不必担心在系统开始处理项目 2 之前等待对项目 1 的转换完成。
Google 的 MapReduce 算法是函数式系统的示例。MapReduce 允许将数据集(例如“所有网站”)视为项目序列。MapReduce 然后有不同的处理器,每个处理器接收可以独立处理的小工作项。
有关函数式语言的更多信息,请参阅 维基百科上的函数式编程 和 Wikibooks 上的函数式编程。
因为 XQuery 也是一种函数式语言,所以您也可以确信,传递给 XQuery 函数的大量项目列表可以独立地在许多处理器上运行,而不用担心如果项目乱序处理会导致结果错误。
在以下示例中,我们将声明两个函数。然后,我们将通过将这些函数应用于序列中的每个项目来处理单词列表。我们将通过将函数名作为参数传递给另一个函数来实现这一点。
注意:这似乎只在 eXist 1.3 中有效。eXist 版本 1.2.X 与 QName() 函数关联了错误的数据类型。
eXist 系统需要将每个函数转换为函数标识符。为此,它需要调用 util:function()。util:function 接受两个参数,函数的限定名称(前缀和函数名)以及函数的元数。在本例中,函数的 元数 是函数接受的参数数量。第一个参数的数据类型必须为 QName 类型。第二个参数(元数)的数据类型为整数。
util:function($function as xs:QName, $arity as xs:integer) as function
declare namespace fw = "http://www.cems.uwe.ac.uk/xmlwiki/fw";
declare function fw:apply($words as xs:string*, $my-function function(item()) as item()) {
for $word in $words
return util:call($my-function,$word)
};
declare function fw:f1($string) {
string-length($string)
};
declare function fw:f2($string) {
substring($string,1,1)
};
let $f1 := util:function(QName("http://www.cems.uwe.ac.uk/xmlwiki/fw","fw:f1"),1)
let $mywords := ("red","green","purple")
return
<hofs>
<data>{$mywords}</data>
<hof>
<task>length of each string</task>
<result>{fw:apply($mywords,$f1)}</result>
</hof>
<hof>
<task>Initial letter of each string</task>
<result>{ fw:apply($mywords, util:function(QName("http://www.cems.uwe.ac.uk/xmlwiki/fw","fw:f2"),1) ) }</result>
</hof>
</hofs>