Subject: Re: [xsl] Here's how to create a function that has context, without passing it context From: Dimitre Novatchev <dnovatchev@xxxxxxxxx> Date: Fri, 16 Nov 2012 16:17:18 -0800 |
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@xxxxxxxxxxxx> 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 > -- 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.
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Here's how to create a fu, Michael Kay | Thread | Re: [xsl] Here's how to create a fu, Liam R E Quin |
Re: [xsl] Here's how to create a fu, Michael Kay | Date | Re: [xsl] Here's how to create a fu, Liam R E Quin |
Month |