[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: Re: XPath 2.0: Problems with the two boolean const

Subject: 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
xpath 2.0 xmlns
> >
> > 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

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.