[Date Prev]
| [Thread Prev]
| [Thread Next]
| [Date Next]
--
[Date Index]
| [Thread Index]
Re: [xml-dev] Implementing Closures in XSLT/XPath 3.0
- From: Ihe Onwuka <ihe.onwuka@gmail.com>
- To: "xml-dev@lists.xml.org" <xml-dev@lists.xml.org>, xsl-list <xsl-list@lists.mulberrytech.com>
- Date: Sun, 18 Nov 2012 06:54:46 +0000
On Sat, Nov 17, 2012 at 11:21 PM, Costello, Roger L. <costello@mitre.org> wrote:
> Hi Folks,
>
> Closures are really cool and really powerful.
> In this paper I describe what closures are, why
> they are important, and how to implement
> them in XSLT 3.0 and XPath 3.0.
>
> More ... http://www.xfront.com/Implementing-Closures-in-XSLT-XPath-3-0.pdf
>
> /Roger
>
A number of comments are in order here - I appreciate that in some
instances I'll be preaching to the choir.
First a general observation. I read alot of (and learn alot from)
Roger's articles but I don't think it is instructive to learn about
closures this way. If you already know what a closure is, implementing
them in 3.0 or any other language is simply a matter of grokking the
syntax. If you didn't know what a closure was before I doubt that
having read about them you will, armed with this new awareness
subsequently go around looking for where and how to deploy this newly
found concept. In the next paragraph I will elaborate why.
Roger stumbled upon closures; in my case I asked my university
professor what a closure was and he said
"You know what it is, you just don't know that's what they're called"
(and he never went on to explain them to me).
This is because (and it will become apparent from what follows)
closures are a natural consequence of higher order programming
The passages in <quote>s are from the paper.
<quote>For a long time many programming languages did not allow you to
pass a function to a function nor create a function that returned a
function nor assign a function to a variable.
Thus functions were treated as second-class values. But many modern
programming languages have elevated functions to first-class
values.</quote>
That makes it sound like higher order functions are a new phenomenon.
They are not - closures as a concept date back to 1964, the first
language to introduce closures and higher order functions as we know
them today was Scheme in 1975
http://en.wikipedia.org/wiki/Closure_%28computer_science%29
<quote>Functions that manipulate functions are called higher-order
functions.</quote>
A higher order function is a function that takes a function as
argument and/or produces a function as it's value (see amongst others
Ullman - Elements of ML Programming or Clack et al Programming with
Standard ML)
<quote>Let’s see how to implement higher-order functions using XSLT
3.0 and XPath 3.0.......
function(
$value as xs:decimal,
$f as function(item()*) as item()*
)
as xs:decimal
{$f($value)}</quote>
Any indenting faux pas above are my own but I don't think the
X(Path|SLT) syntax is at all helpful in explicating the concepts.
Here's the same idea in lambda calculus
&lgr;f x -> f x
is a function that takes 2 arguments, a function f and a value x and
returns the result of applying f to x.
In a real programming language like ML it's not much different
fn f x -> f x - which as defined is anonymous. I believe you can give
it a name like so fn apply = fn f x - f x.
Now if f is a function that converts Celsius to Fahrenheit apply f 100
will give 212.
Apply is a higher order function because it takes a function as an
argument thereby fulfilling one of the criteria stipulated as
sufficient in the definition (note there was no requirement to and we
did not manipulate f).
As to what is a closure - again the X(Path|SLT) syntax is a barrier to
explication so instead I will illustrate with the sort of example that
led my prof to make the aforementioned comment this time I will use
Scheme. After a while I would write things like
(define times
(lambda (x)
(lambda (y) (* x y))))
If the parens put you of,f here it is much less verbosely in lambda
calculus &lgr;x ->&lgr;y -> * x y (we assume * as a lambda calculus
primitive).
In SML it is
fun times x = fn y -> (*) x y
Referencing whichever versions suits your fancy, we are defining a
function that takes an argument that we have called x and returns a
function that takes a single argument y but manipulates two arguments
(x and y) to give it's result - using the last example the result is a
function
fn y -> (*) x y
In the above function x is used in the body but is not an argument -
we say it occurs free in the function. A closure is created when we
provide bindings (values) for the free variables and these bindings
are created by looking the variable up in the environment that existed
when the closure was created.
So in the above example we look up the value of x - in this case it is
provided as a parameter to times so
times 2
creates an environment where x takes the value of 2 and closure we
create fn y -> (*) 2 y doubles it's argument. Similarly times 3 will
create a closure that triples it's argument etc.
We can now say
let val double = times 2
let val triple = times 3
let val quadruple = times 4
each of the above creates a closure in which the value given to the
free variable is fixed at the value that was derived from the
environment that existed when the closure was defined.
This is how I and I am sure many others happily utilised closures
without ever knowing what they were called.
[Date Prev]
| [Thread Prev]
| [Thread Next]
| [Date Next]
--
[Date Index]
| [Thread Index]