我想创建一个无界序列,想知道是否可以通过尾递归函数来做到这一点。
一个简单的例子是
<xsl:function name="kooks:repeat" as="xs:integer*">
<xsl:sequence select="1"/>
<xsl:sequence select="kooks:repeat()"/>
</xsl:function>
<xsl:template match="/">
<xsl:sequence select="kooks:repeat()[5]"/>
</xsl:template>
(我使用的是 Saxon-ee 11.4)
失败了
Severity: error
Description: class java.lang.StackOverflowError
我认为问题是因为有 2 个序列语句,然后 saxon 将其解释为追加/cons 操作,因此该函数不再是尾递归(在其模型中)。
如果我们将其与 F# 代码(我正在尝试将其转换为 XSLT)进行比较
let rec ones () =
seq {
yield 1
yield! ones ()
}
let tenMillionthEntry =
ones ()
|> Seq.skip 10000000
|> Seq.take 1
|> Seq.head
这还不考虑连续收益率,收益率!作为函数中的操作,因此其尾递归优化有效(大概是因为此代码不会崩溃)。
XML slack 上的 Christian Grün 提出了如下观点:
let $inf-rec := function($start, $self) {
map {
'skip': function($c) { $self($start + $c, $self) },
'take': function($c) { $start to $start + $c - 1 }
}
},
$inf := function() {
$inf-rec(1, $inf-rec)
}
return $inf()?skip(10000000)?take(1) ! head(.)
他还说在 XPath 4.0 中有函数 https://qt4cg.org/specifications/xpath-functions-40/Overview.html#func-do-until 和 https://qt4cg.org/specifications/xpath -functions-40/Overview.html#func-while-do 可能有帮助。
还要等待 Dimitre Novatchev 是否出现来解释他在 XPath 4 中无限序列的想法。