This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: XPath's role (Was: Re: Re: . in for)


Hi Mike,

> If it can be shown that user-defined functions can handle all cases
> that would otherwise need range variables, that would certainly be
> an interesting argument to use.

I'm not sure I can *prove* anything (left my mathematical years behind
a while ago), so this is probably something for David or Dimitre. But
isn't it provable from the fact that any iteration over a sequence can
be performed by recursing over the sequence?

Taking the basic example:

  for $item in $sequence return some:function($item)

is equivalent to:

<xsl:function name="my:for">
  <xsl:param name="sequence" type="item*" />
  <xsl:result select="if (empty($sequence))
                      then ()
                      else (my:function($sequence[1]),
                            my:for($sequence[position() > 1]))" />
</xsl:function>

with the call:

  my:for($sequence)


Introducing a second range variable:

  for $item1 in $sequence1,
      $item2 in $sequence2
  return some:function($item1, $item2)

is equivalent to:

<xsl:function name="my:for1">
  <xsl:param name="sequence1" type="item*" />
  <xsl:param name="sequence2" type="item*" />
  <xsl:variable name="item1" select="$sequence1[1]" />
  <xsl:result select="if (empty($sequence1))
                      then ()
                      else (my:for2($item1, $sequence2),
                            my:for1($sequence1[position() > 1],
                                    $sequence2))" />
</xsl:function>

<xsl:function name="my:for2">
  <xsl:param name="item1" type="item" />
  <xsl:param name="sequence2" type="item*" />
  <xsl:variable name="item2" select="$sequence2[1]" />
  <xsl:result select="if (empty($sequence2))
                      then ()
                      else (some:function($item1, $item2),
                            my:for2($item1,
                                    $sequence2[position() > 1]))" />
</xsl:function>

which you would call with:

  my:for1($sequence1, $sequence2)

[Note that any filtering of $sequence2 based on the items in
$sequence1 can be handled in some:function() in the general case.]


You can continue doing this ad infinitum, I believe, each time adding
another my:for() function to handle the additional range variable.

Of course there's a difference between proving that you *can* do all
for expressions with user-defined functions and stating that you'd
*want* to do all for expressions with user-defined functions. And I
can quite understand people looking at the above and going 'I'd rather
write a for expression than all of that!'

But in real life, I think the vast majority of the use cases for the
for expression (in XSLT) can be handled with a simple mapping
operator. And hardly any need more than a single function (plus a
simple mapping operator). The existential semantics of the various
comparison operators help enormously, of course. Plus, the only reason
you need to use a function rather than a xsl:for-each (or equivalent)
is if (a) some:function() returns nodes and (b) you don't want to lose
the identity of those nodes.

Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]