3

由于我一直在做一些遗留工作,我最近一直在学习如何在 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]是否期望您将多个“功能”传递$pFuncfoldl

在我见过的所有函数式编程示例中,参数 f 是单独传递的,而不是作为列表传递的,这个 Haskell 部分函数定义: foldl f z (x:xs) = foldl f (f z x) xs

4

2 回答 2

5

我相信我是一个“可信且官方”的消息来源,因为我恰好是 FXSL 的作者 :)

我的问题与vFunResult变量有关。我知道它正在使用$pFunc模板制作一个“功能”应用程序,但为什么 [1]选择器,为什么是arg0 in the template call being set to $pFunc[position > 0] ? Is it expected that you are passing more than one 'function' in$pFunc tofoldl` ?

首先,这是一个很好的观察。您是 13 年来第一个注意到这一点的人。

这有纯粹的历史原因。2001 年我写 FXSL 时,我还在学习 Haskell 和函数式编程。

在某些问题中,折叠显然是解决方案,但是,我们指定的函数需要一个额外的参数。正如我所说,我只是在编写这些函数,我还没有弄清楚如何实现部分应用(这是在四个月后通过引入curry()函数完成的。(见这里: http: //fxsl.sourceforge.net /articles/PartialApps/Partial%20Applications.html#4._Using_currying_and_partial_application_-_the_iter_and_power_functions。)这就是为什么当时我决定在这种情况下,可以将附加参数作为列表的尾部传递,其第一项是“官方”的foldl预期功能。

我确实注意到 fxsl.sourceforge.net/articles/FuncProg/2.html#List_processing 上的所有示例都只传递了一个模板$pFunc...所以我最初的想法是arg0通常被忽略$pFuncs

这不是一个正确的结论。

请参阅此处: http: //fxsl.sourceforge.net/articles/FuncProg/2.html 如何minimum / maximum实现这些功能。他们期望作为$arg0一个附加函数被传递,它实现了<比较。因此这些函数是完全通用的,并且不依赖于列表中项目的数据类型。

无论如何,正如我所说,问题中的观察反映了纯粹的历史事实。如果查看 FXSL 2.0 的代码,这个“功能”就完全消失了:http://fxsl.cvs.sourceforge.net/viewvc/fxsl/fxsl-xslt2/f/func-foldl.xsl?revision=1.3& view =标记

并且该函数本质上定义为 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: //conferences.idealliance.org/extreme/html/2006/Novaatchev01/EML2006Novaatchev01.html

在 XSLT 2.0 中,几乎可以完全使用 XPath 2.0 编写大多数 FXSL 函数并作为单行代码。

而且,当然,您需要查看 W3C XPath 3.0 规范:http ://www.w3.org/TR/xpath-30/#id-inline-func ,其中高阶函数 (HOF) 已经完全是其中的一部分的语言。您也可能对我上个月在 Balisage 2013 会议上发表的论文感兴趣:“Programming in XPath 3.0”。论文在这里: http ://t.co/p3mdgoTdgj

不过,PPT 演示可能更有趣:https ://t.co/i5xCTUObvp

于 2013-09-12T03:58:21.707 回答
3

pFunc是一个列表,因此foldl可以应用本身需要附加参数的函数。附加参数pFunc[position() > 1]通过arg0传递给pFunc[1]给出的函数。

例如,查看 FXSL最小函数,它可以采用比较函数pCMPFun,然后它可以通过pFunc[position() > 1]传递给foldl

     <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>
于 2013-09-12T03:36:20.890 回答