xsl-list
[Top] [All Lists]

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

2003-10-09 11:09:49


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