由于我一直在做的一些遗留工作,我最近一直在学习如何在XSLT 1.0中使用函数式编程结构。所以我一直在学习更多关于FXSL的知识,并对foldl有一些疑问。
<xsl:template name = "foldl" >
<xsl:param name = "pFunc" select = "/.." />
<xsl:param name = "pA0" />
<xsl:param name = "pList" select = "/.." />
<xsl:choose>
<xsl:when test = "not($pList)" >
<xsl:copy-of select = "$pA0" />
</xsl:when>
<xsl:otherwise>
<xsl:variable name = "vFunResult" >
<xsl:apply-templates select = "$pFunc[1]" >
<xsl:with-param name = "arg0" select = "$pFunc[position() > 1]" />
<xsl:with-param name = "arg1" select = "$pA0" />
<xsl:with-param name = "arg2" select = "$pList[1]" />
</xsl:apply-templates>
</xsl:variable>
<xsl:call-template name = "foldl" >
<xsl:with-param name = "pFunc" select = "$pFunc" />
<xsl:with-param name = "pList" select = "$pList[position() > 1]" />
<xsl:with-param name = "pA0" select = "$vFunResult" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
我的问题与vFunResult
变量有关。我知道它正在使用$pFunc
模板创建一个“函数”应用程序,但为什么[1]
选择器,以及为什么模板调用中的arg0设置为$pFunc[position > 0]
? 您是否希望将$pFunc
中的多个“功能”传递给foldl
?
在我看过的所有函数式编程示例中,参数f单独传递而不是作为列表传递,这个Haskell部分函数定义:foldl f z (x:xs) = foldl f (f z x) xs
答案 0 :(得分:5)
我相信我是一个“可信和官方”的来源,因为我碰巧是FXSL的作者:)
我的问题与
vFunResult
变量有关。我明白了 用$pFunc
模板制作一个“功能”应用程序,但为什么要这样做[1]
选择器,为什么是arg0 in the template call being set to
$ pFunc [position&gt; 0]? Is it expected that you are passing more than one 'function' in
$ pFuncto
foldl`?
首先,这是一个很好的观察。你是13年来第一个注意到这一点的人。
这纯粹是历史原因。在2001年我写过FXSL时,我还在学习Haskell和函数式编程。
在某些问题中,折叠显然是解决方案,但是,我们指定的功能需要一个额外的参数。正如我所说,我只是编写这些函数,而我还没有想出如何实现部分应用程序(这是在四个月后通过引入curry()
函数完成的。(参见此处:{{3}这就是为什么当时我决定在这种情况下,附加参数可以作为列表的尾部传递,其第一项是foldl
期望的“官方”函数。
我注意到了所有的例子 仅限fxsl.sourceforge.net/articles/FuncProg/2.html#List_processing 在
$pFunc
中传递一个模板...所以我最初的想法是arg0
一般来说$pFuncs
会被忽略吗?
这不是一个正确的结论。
请参阅此处:http://fxsl.sourceforge.net/articles/PartialApps/Partial%20Applications.html#4._Using_currying_and_partial_application_-_the_iter_and_power_functions minimum / maximum
函数的实现方式。他们期望$arg0
传递一个额外的函数,实现<
比较。因此,这些函数是完全通用的,并且不依赖于列表中项目的数据类型。
无论如何,正如我所说,问题中的观察反映了一个纯粹的历史事实。如果查看FXSL 2.0的代码,这个“功能”就完全消失了:http://fxsl.sourceforge.net/articles/FuncProg/2.html
并且该函数基本上定义为XPath 2.0单行:
<xsl:sequence select=
"if (empty($pList))
then
$pA0
else
f:foldl($pFunc,
f:apply($pFunc, $pA0, $pList[1]),
$pList[position() > 1]
)"/>
最后,感谢您对FXSL的兴趣。我建议您查看FXSL 2.x(适用于XSLT 2.0)并阅读2006年在Extreme Markup Languages会议上发表的论文:http://fxsl.cvs.sourceforge.net/viewvc/fxsl/fxsl-xslt2/f/func-foldl.xsl?revision=1.3&view=markup
在XSLT 2.0中,几乎可以使用XPath 2.0和单行编写大部分FXSL函数。
当然,您需要查看W3C XPath 3.0规范:http://conferences.idealliance.org/extreme/html/2006/Novatchev01/EML2006Novatchev01.html,其中高阶函数(HOF)已经完全成为该语言的一部分。您可能也对我上个月在Balisage 2013会议上发表的论文感兴趣:“在XPath 3.0中编程”。论文在这里:http://www.w3.org/TR/xpath-30/#id-inline-func
然而,PPT演示可能更有趣:http://t.co/p3mdgoTdgj
答案 1 :(得分:3)
pFunc 是一个列表,因此 foldl 可以应用自身需要其他参数的函数。附加参数 pFunc [position()&gt; 1] ,通过 arg0 传递给 pFunc [1] 给出的函数。
例如,查看FXSL minimum 功能,它可以采用比较功能 pCMPFun ,然后又可以通过 foldl 通过 pFunc [position()&gt; 1] 强>:
<xsl:template name = "minimum" >
<xsl:param name = "pList" select = "/.." />
<xsl:param name = "pCMPFun" select = "/.." />
<xsl:variable name = "vdfCMPFun"
select = "document('')/*/minimum-own-compare:*[1]" />
<xsl:variable name = "vFoldFun"
select = "document('')/*/minimum-pick-smaller:*[1]" />
<xsl:if test = "$pList" >
<xsl:variable name = "vCMPFun"
select = "$pCMPFun | $vdfCMPFun[not($pCMPFun)]" />
<xsl:variable name = "vFuncList" >
<xsl:copy-of select = "$vFoldFun" /> <!-- Pick Smaller -->
<xsl:copy-of select = "$vCMPFun" /> <!-- Compare -->
</xsl:variable>
<xsl:call-template name = "foldl" >
<xsl:with-param name = "pFunc"
select = "msxsl:node-set($vFuncList)/*" />
<xsl:with-param name = "pList" select = "$pList" />
<xsl:with-param name = "pA0" select = "$pList[1]" />
</xsl:call-template>
</xsl:if>
</xsl:template>