3

I've been learning about using functional programming constructs in XSLT 1.0 lately, due to some legacy work I've been doing. So I've been learning more about FXSL, and have some questions about 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>

My question has to do with the vFunResult variable. I get that it is making a 'function' application with the $pFunc template, but why the [1] selector, and why is the arg0 in the template call being set to $pFunc[position > 0]? Is it expected that you are passing more than one 'function' in $pFunc to foldl?

In all the functional-programming examples that I've seen, the parameter f is passed in singularly and not as a list, ala this Haskell partial function definition: foldl f z (x:xs) = foldl f (f z x) xs

J. Polfer
  • 12,251
  • 10
  • 54
  • 83
  • I did notice that all the examples on http://fxsl.sourceforge.net/articles/FuncProg/2.html#List_processing only pass one template in $pFunc... so my initial thought is that arg0 is ignored by the $pFuncs in general? – J. Polfer Sep 09 '13 at 20:38

2 Answers2

5

I believe that I am a "credible and official" source, as I happen to be the author of FXSL :)

My question has to do with the vFunResult variable. I get that it is making a 'function' application with the $pFunc template, but why the [1] selector, and why is the arg0 in the template call being set to $pFunc[position > 0]? Is it expected that you are passing more than one 'function' in$pFunctofoldl` ?

First of all, that is a good observation. You are the first in 13 years to notice this.

This has purely historical reasons. When in 2001 I wrote FXSL, I was still learning Haskell and functional programming.

In some problems a fold is clearly the solution, however, the function that we specify expects one additional parameter. As I said, I was just writing these functions, and I hadn't yet figured out how to implement partial application (this was done a four months later by introducing the curry() function. (see here: http://fxsl.sourceforge.net/articles/PartialApps/Partial%20Applications.html#4._Using_currying_and_partial_application_-_the_iter_and_power_functions. ) This is why at that time I decided that in such cases, the additional parameters can be passed as the tail of a list, whose first item is the "official" function that foldl expects.

I did notice that all the examples on fxsl.sourceforge.net/articles/FuncProg/2.html#List_processing only pass one template in $pFunc... so my initial thought is that arg0 is ignored by the $pFuncs in general?

This is not a correct conclusion.

Do see here: http://fxsl.sourceforge.net/articles/FuncProg/2.html how the minimum / maximum functions are implemented. They expect as $arg0 an additional function to be passed, that implements the < comparison. Thus these functions are completely general, and do not depend on the data type of the items in the list.

Anyway, as I said, the observation made in the question reflects a pure historical fact. If one looks into the code of FXSL 2.0, this "feature" is completely gone: http://fxsl.cvs.sourceforge.net/viewvc/fxsl/fxsl-xslt2/f/func-foldl.xsl?revision=1.3&view=markup

and the function is essentially defined as an XPath 2.0 one-liner:

  <xsl:sequence select=
         "if (empty($pList))
              then 
                  $pA0
              else
                  f:foldl($pFunc, 
                          f:apply($pFunc, $pA0, $pList[1]), 
                          $pList[position() > 1]
                          )"/>

Finally, thank you for your interest in FXSL. I would recommend that you look at FXSL 2.x (for XSLT 2.0) and read my paper from 2006 at the Extreme Markup Languages conference: http://conferences.idealliance.org/extreme/html/2006/Novatchev01/EML2006Novatchev01.html

In XSLT 2.0 it is possible to write most of the FXSL functions almost completely using XPath 2.0 and as one-liners.

And, of course, you need to see the W3C XPath 3.0 specification: http://www.w3.org/TR/xpath-30/#id-inline-func, where Higher-Order Functions (HOFs) are already fully part of the language. You also may be interested in my paper presented last month at the Balisage 2013 conference: "Programming in XPath 3.0". The paper is here: http://t.co/p3mdgoTdgj

However, the PPT presentation is probably more interesting: https://t.co/i5xCTUObvp

Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
3

pFunc is a list so that foldl can apply functions which themselves require additional parameters. The additional parameters, pFunc[position() > 1], are passed via arg0 to the function given by pFunc[1].

For example, check out the FXSL minimum function, which can take a comparison function, pCMPFun, which it in turn can pass through to foldl via pFunc[position() > 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>
kjhughes
  • 106,133
  • 27
  • 181
  • 240
  • 1
    It is a pleasant surprise that there are people like you, who have such deep knowledge of FXSL! I would appreciate your feedback about FXSL and what new features you need to be implemented. – Dimitre Novatchev Sep 12 '13 at 04:32
  • 2
    @Dimitre Novatchev: Surprise is mine that the master was already working on answer when I submitted. Thank you for creating and sharing such a useful library, and thank you too for answering questions here so thoroughly. (I'd upvote your answer but am not yet able -- this was my first answer on SO.) – kjhughes Sep 12 '13 at 11:04