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: Functional trim()


Hi Adriano,

Adriano Rodrigues Ferreira <ferreira at triang dot com dot br> wrote:

> Dimitre Novatchev wrote:
> >What is described above is quite simple -- we trim-left the string, then reverse
> it,
> >then trim-left the reversed string (at this point all the trimming is done), then
> >finally reverse the reversed and trimmed string.
> 
> This solution is immediately understable from the point of view of
> someone used to functional programming. But it is cryptical from
> the point of view of someone looking for a simple solution to
> a simple problem (the XSL code inflates with respect to the Haskell
> code and is quite intimidating).
>
> Strings represented as lists, spaces eaten at the lead, reversed,
> spaces eaten at the lead, reversed. You got be kidding to say this
> is simple.

I'm very serious saying the presented solution is simple. Thank you for asking and
giving me a chance to explain this.

Have you noticed that by now nobody had provided a completely coded solution (there
were only several verbal descriptions of a possible solution, some of them
incorrect)? Can you explain the reason for this?

Part of the answer is that this problem is not one of the easiest and without a
proper foundation its XSLT solution will be long and ugly.

The functional solution is indeed orders of magnitude simpler, because it relies on
a collection -- library -- of existing, pre-coded general functions on lists. 

Having such a library, the solution would be simply:

  <xsl:template match="/">
    '<xsl:call-template name="trim">
        <xsl:with-param name="pStr" select="string(/*)"/>
    </xsl:call-template>'
  </xsl:template>
</xsl:stylesheet>

Just 6 lines of code.

Having to code the "trim" function by re-using the existing library functions is
still a simple and straightforward task:

  <xsl:template name="trim">
    <xsl:param name="pStr"/>
    
    <xsl:variable name="vrtfParam">
      <myReverse:myReverse/>
      <myTrim1:myTrim1/>
      <myReverse:myReverse/>
      <myTrim1:myTrim1/>
    </xsl:variable>

    <xsl:call-template name="compose-flist">
        <xsl:with-param name="pFunList" select="msxsl:node-set($vrtfParam)/*"/>
        <xsl:with-param name="pArg1" select="$pStr"/>
    </xsl:call-template>
    
  </xsl:template>


The same applies for the "trim1" template.

However, I wanted to explain this code (see bellow), and this is why I duplicated
the code of all templates when explaining them. 

[snip]

> The kind of solution that I think it would be natural for the original
> statement of the problem would be something like the Perl function
> 
> sub trim {
>     for (@_) {
>         s/^\s*//; # trim leading spaces
>         s/\s*$//; # trim trailing spaces
>     }
>     return @_;
> }
> 
> The only lines that really matter here are
>         s/^\s*//; # trim leading spaces
>         s/\s*$//; # trim trailing spaces
> and that means 
> (1) match the start of the string ^, (2) scan leading spaces \s*, 
> and (3) trim them. After this step of pattern match and substitution,
> (4) match trailing spaces \s*, (5) match the end of the string $,
> and (6) trim them. (This comes from 
> 	perldoc -q "strip blank space"
> a reference pointed to me by John W. Khran.)
> 
> Now this solution was coded in a few lines
> (being as small as the problem statement). With a pattern match library 
> on XSL, maybe this could look like:
> 
> <xsl:template match="text()" mode="trim">
>      <pattern-match:substitute match-string="^\s*" replace-string=""/>
>      <pattern-match:substitute match-string="\s*$" replace-string=""/>
> </xsl:template>

Now I do not agree that this solution is more understandable. It is brief and
cryptic. In case you disagree, could you try to present a solution that matches
C-like comments (/* A multiline /*comment* here */). Then explain it...

Let me return to your previous statement that:

> the XSL code inflates with respect to the Haskell
> code and is quite intimidating

The purpose of my message was not only to present a solution. If this was the only
purpose, I could just provide the "trim" template.

What I really wanted to do was to present and discuss the code of almost all
re-usable constituents (with the only exception of "reverse", which had been
discussed before), in order to be able to emphasize some key ideas -- in this case
using functional composition, the fact that we can express a solution to a more
complex problem by breaking it down to simpler sub-problems and re-using ready,
pre-coded library functions, to emphasize once again the great value of having
general list-processing library functions that can almost always be used (and often
in unanticipated ways) and combined together to produce the solution of almost any
problem.

Imagine now, that you had to provide the code of the regular expressions interpreter
and explain it -- probably you and I would agree that in this case ***your*** code
and comments would be orders of magnitudes longer.

The regular expressions solution certainly is a very good and compact one (I'm not
using "natural" here as this is a very relative and imprecise concept).

However, reqular expressions by design target only the specific class of
text-processing problems. This is why I still value more a more general approach
targeting some of the most generic list/tree/function processing problems.

With these one can easily solve text -processing problems (e.g. text
formatting/justification -- see "Re: Line breaking for text":
http://aspn.activestate.com/ASPN/Mail/Message/XSL-List/948073)

or create and display shapes and regions, or create and display animations, or
create music (see Paul Hudak's book "The Haskell School of Expression"), or
differentiate and integrate, or ...

As you can see, the list of possibilities of the functional programming approach is
open-ended.

> A few days ago someone has asked about pattern matching abilities in XSL,
> which XSL 1.0 specification predicted for XSL 2.0. Michael Kay told him
> to take a look at some documents on preparation. This is the kind of library 
> functions 
> which will give this kind of problem really simple solutions.
> 
> The toolkit available to XSL programmers would become quite powerful
> with additions such as the pattern match library. And some questions on the 
> XSL list would be answered with shorter pieces of codes. 

Until XPath and XSLT include support for higher-order functions, there will always
be lots and lots of problems not covered by the finite and too-specific, limited
supported functionality. Until then, for the many questions that would not be
possible to answer "with shorter pieces of codes", the existence and use of a
general and freely available FP library will be the way to create simple and
understandable solutions, to make things easier and possible, which were difficult
or impossible before, to help people not re-invent the wheel and to better see laws
and relationships where thew saw none before, and ultimately to save many hours of
their time.

Thank you once again for starting this discussion.

Cheers,
Dimitre Novatchev.
 

__________________________________________________
Do You Yahoo!?
Send your FREE holiday greetings online!
http://greetings.yahoo.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]