xsl-list
[Top] [All Lists]

Re: [xsl] Here's how to create a function that has context, without passing it context

2012-11-16 18:17:48
Even more simply, one can use a function, which has been created as a
partial application of another function, passing a subset of all
required arguments -- these form the "context".

Cheers,
Dimitre

On Fri, Nov 16, 2012 at 4:07 PM, Michael Kay <mike(_at_)saxonica(_dot_)com> 
wrote:


Your example can actually be achieved rather more simply, because
functions have always had access to global variables. You could have done
this using only 2.0 features:

<xsl:variable name="root" select="/"/>

<xsl:function name="f:author">
  <xsl:param name="arg" as="xs:string"/>
  <xsl:sequence select="$root//author[name=$arg]"/>
</xsl:function>

But what you're starting to discover, I think, is the fact that a
dynamically-created function can hold data as well as algorithm. The data
(which you call "context") usually goes by the name of a "closure":
basically, at the time the function is created, it can "capture" the values
of all local variables that are in scope at the time it was created, and use
these values when it is subsequently invoked. The joys of functional
programming!

Michael Kay
Saxonica



On 16/11/2012 23:28, Costello, Roger L. wrote:

Hi Folks,

Suppose that you would like to create a function that, given the title of
a book, it returns the author.

For example, this function call:

     author('The Society of Mind')

returns this author:

      Marvin Minsky

Notice that the function, author(), was just provided a string and no
context.

How can the function obtain the author without being given any context?
Recall that functions supposedly have no context and you must give it
(through parameters) all the context it needs.

In this message I show how to create functions that have context, but you
don't have to give it the context.

This technique is so cool.

Here is the XML document that the function will operate on:

<Books>
     <Book>
           <Title>Six Great Ideas</Title>
           <Author>Mortimer J. Adler</Author>
     </Book>
     <Book>
           <Title>The Society of Mind</Title>
           <Author>Marvin Minsky</Author>
     </Book>
</Books>

I create a variable, author, that is defined to be an XPath 3.0 anonymous
function:

<xsl:variable name="author" select="... define author as an anonymous
function ... " />

Then I invoke the "author function" with a string representing the title
of a book:

<xsl:value-of select="$author('The Society of Mind')" />

Here is the output:

        Marvin Minsky

This is the key to the technique:

       Create a variable that is defined to be a function that returns a
function.

Wow!

We need to step through this very carefully.

I create a variable, root, to which I pass the root element of the XML
document (Books):

     <xsl:variable name="root" select="function(

$root_ as element(Books)

)


The function returns a function:

     <xsl:variable name="root" select="function(

$root_ as element(Books)

)

as function(xs:string) as item()


The function that is returned takes an argument that is a string
representing the title of a book and it returns the author of the book:

     <xsl:variable name="root" select="function(

$root_ as element(Books)

)

as function(xs:string) as item()
                                         {function($title as xs:string)
as item() {$root_/Book[Title eq $title]/Author}}" />


Remember the author variable? It gets the returned function:

     <xsl:variable name="author" select="$root(/Books)" />


Okay, let's put it all together:
--------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet  xmlns:xsl="http://www.w3.org/1999/XSL/Transform";

xmlns:xs="http://www.w3.org/2001/XMLSchema";
                                version="3.0">
          <xsl:output method="text"/>
          <xsl:variable name="root" select="function(

$root_ as element(Books)

)

as function(xs:string) as item()
                                         {function($title as xs:string)
as item() {$root_/Book[Title eq $title]/Author}}" />

     <xsl:variable name="author" select="$root(/Books)" />
          <xsl:template match="Books">
         <xsl:value-of select="$author('The Society of Mind')" />
     </xsl:template>
     </xsl:stylesheet>
--------------------------------------------------------

Pretty cool, aye?

/Roger

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: 
<mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--




--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: 
<mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--




--
Cheers,
Dimitre Novatchev
---------------------------------------
Truly great madness cannot be achieved without significant intelligence.
---------------------------------------
To invent, you need a good imagination and a pile of junk
-------------------------------------
Never fight an inanimate object
-------------------------------------
To avoid situations in which you might make mistakes may be the
biggest mistake of all
------------------------------------
Quality means doing it right when no one is looking.
-------------------------------------
You've achieved success in your field when you don't know whether what
you're doing is work or play
-------------------------------------
Facts do not cease to exist because they are ignored.
-------------------------------------
Typing monkeys will write all Shakespeare's works in 200yrs.Will they write
all patents, too? :)
-------------------------------------
I finally figured out the only reason to be alive is to enjoy it.

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--