[xsl] Re: Re: XPath 2.0: Problems with the two boolean constants true and false

Subject: [xsl] Re: Re: XPath 2.0: Problems with the two boolean constants true and false
From: "Dimitre Novatchev" <dnovatchev@xxxxxxxxx>
Date: Thu, 9 Oct 2003 20:09:49 +0200
> >
> > This is the bit that I don't understand. You must know something
> > about the values produced by the code you are calling, otherwise the
> > result is meaningless to the caller. What isn't clear to me (though
> > Jeni seems to have divined it in her usual way...) is what kind of
> > contract you want to have between the calling code and the called
> > code. Usually this contract is expressed in terms of types; if you
> > want to express it some other way, then I would like to understand
> > that.
>
> As I think you know, many of the generic templates that Dimitre uses
> in FXSL have "functions" as parameters. For example, the "map"
> function takes a sequence and a function as parameters, and returns
> the sequence constructed by applying the function on each of the items
> in the sequence.
>
> In these templates, you don't need to know what the function actually
> *does*, and therefore don't need to know what types of parameters it
> expects (as long as you know *how many* parameters it expects, I
> think).
>
> For example, you could imagine a kind of 'join' function that takes
> two sequences plus a two-argument function and returns a single
> sequence that is the result of applying the function on each pair of
> values from the two sequences. This would work with the 'and' function
> (which expects two booleans) or a 'plus' function (which expects two
> numbers).
>
> If you call the 'join' function directly, you know statically that the
> two sequences have to be booleans (or numbers) and that the result is
> a sequence of booleans (or numbers), based on the function that you
> pass to the 'join' function. So as a programmer using the function of
> course you know what it does. However, the implementation of the
> 'join' function is completely generic and it can't tell the types of
> the arguments or result of the function that it's passed (since we
> don't have reflection).


Wow... Jeni, what an excellent explanation!

Mike, here's an actual example from my latest work on FXSL for XSLT2:

func-apply.xsl:
==========
<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
 xmlns:f="http://fxsl.sf.net/";
 exclude-result-prefixes="f"
>

  <xsl:function name="f:apply">
   <xsl:param name="pFunc" as="element()"/>
   <xsl:param name="arg1"/>

    <xsl:apply-templates select="$pFunc">
      <xsl:with-param name="arg1" select="$arg1"/>
    </xsl:apply-templates>
  </xsl:function>

  <xsl:function name="f:apply">
   <xsl:param name="pFunc" as="element()"/>
   <xsl:param name="arg1"/>
   <xsl:param name="arg2"/>

    <xsl:apply-templates select="$pFunc">
      <xsl:with-param name="arg1" select="$arg1"/>
      <xsl:with-param name="arg2" select="$arg2"/>
    </xsl:apply-templates>
  </xsl:function>

<!-- The rest -- definitions of f:apply up to having 10 arguments
 ommitted -->
</xsl:stylesheet>

func-foldl.xsl:
==========
<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
 xmlns:f="http://fxsl.sf.net/";
 exclude-result-prefixes="f"
>
    <xsl:import href="func-apply.xsl"/>

    <xsl:function name="f:foldl">
      <xsl:param name="pFunc" as="element()"/>
      <xsl:param name="pA0"/>
      <xsl:param name="pList" as="item()*"/>

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


testFunc-Foldl.xsl:
=============
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
xmlns:foldl-func="foldl-func"
xmlns:f="http://fxsl.sf.net/";
exclude-result-prefixes="f foldl-func"
>

   <xsl:import href="func-foldl.xsl"/>

   <!-- This transformation must be applied to:
        numList.xml
     -->
   <foldl-func:foldl-func/>
   <xsl:variable name="vFoldlFun" select="document('')/*/foldl-func:*[1]"/>
    <xsl:output  encoding="UTF-8" omit-xml-declaration="yes"/>

    <xsl:template match="/">
      <xsl:value-of select="f:foldl($vFoldlFun, 1, 1 to 10 )"/>
    </xsl:template>

    <xsl:template match="*[namespace-uri() = 'foldl-func']">
         <xsl:param name="arg1" select="0"/>
         <xsl:param name="arg2" select="0"/>

         <xsl:value-of select="$arg1 * $arg2"/>
    </xsl:template>
</xsl:stylesheet>

As we see, the function f:foldl() is a higher-order function, which is
passed a reference to a template and applies it to two arguments.

What is only known, id that the template passed as parameter accepts these
two parameters in the specified order and produces a result, which will
later be used in the recursive chain of operations.

The last stylesheet is an example of using f:foldl() to calculate the
product of the items of a sequence of numbers. The one that follows uses
f:foldl to say if all of the items of a sequence are true. To do this, we
just specify other parameters to f:foldl -- a template that performs a
logical and and an initial value of true (or 1):

func-allTrue.xsl:
===========
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
xmlns:xs="http://www.w3.org/2001/XMLSchema";
xmlns:fxl="http://fxsl.sf.net/";
xmlns:allTrue-And="allTrue-And"
exclude-result-prefixes="fxl xs allTrue-And"
>
  <xsl:import href="func-foldl.xsl"/>

  <allTrue-And:allTrue-And/>

  <xsl:function name="fxl:allTrue" as="xs:boolean" >
    <xsl:param name="pList" as="xs:boolean*"/>

    <xsl:variable name="vAnd" select="document('')/*/allTrue-And:*[1]"/>

    <xsl:copy-of select="fxl:foldl($vAnd, 1, $pList)"/>
  </xsl:function>

  <xsl:template name="And" match="*[namespace-uri()='allTrue-And']">
    <xsl:param name="arg1"/>
    <xsl:param name="arg2"/>
         <xsl:value-of select="xs:boolean($arg1) and xs:boolean($arg2)"/>
  </xsl:template>
</xsl:stylesheet>

this can further be used as a base for more complex functions, etc.

So which is the best way to specify (or not specify) parameter and
return-value type information for the template, passed as parameter to
f:apply()?


=====
Cheers,

Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL





 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread