SIDENOTE: @amike: The run was good while it lasted, eh? ;-)
SIDENOTE.NEXT: After rereading the title, I’m not even sure it makes any sense. But then again, what’s new? ;-) :D
—
[Post.Body]
DonXml’s All Things Techie : Mixing Object, Functional and Aspect Oriented Programming
Within a DSL it would be cool if you could map its Nouns to Objects (described via OOP), its Verbs to Functions (described via FP), and its Adjectives and Adverbs to Aspects (via AOP).
I have to do some research, but does this fit within the definition of a composable language? I tried to fine a definition of what a composable language, but didn’t seem to find one.
Oh, the power of XSLT 2.0 (and XPath 2.0), where you can bring together the knowledge-pool and massive underlying code base of OOP, fold in the power of Functional Programming, and weave all of it together with AOP to produce a truly composable language as a result.
For example,
<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform xmlns="http://nuxleus.com/message/response" xmlns:lookup="http://nuxleus.com/message/response/lookup" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:saxon="http://saxon.sf.net/" xmlns:clitype="http://saxon.sf.net/clitype" xmlns:at="http://atomictalk.org" xmlns:func="http://atomictalk.org/function" xmlns:queue-manager="clitype:Xameleon.Function.QueueManager?partialname=Xameleon" xmlns:aspnet-context="clitype:System.Web.HttpContext?partialname=System.Web" xmlns:queue="http://xameleon.org/service/queue" xmlns:guid="clitype:System.Guid?partialname=mscorlib" version="2.0" exclude-result-prefixes="#all">
<xsl:import href="../../base.xslt" />
<xsl:param name="current-context"/>
<xsl:output method="xml" indent="no" />
<xsl:variable name="response-output">
<lookup:response-code-lookup>
<lookup:message response-code="message sent">
<lookup:human-readable>Message was sent successfully!</lookup:human-readable>
</lookup:message>
<lookup:message response-code="error">
<lookup:human-readable>There was an error sending your message.</lookup:human-readable>
</lookup:message>
</lookup:response-code-lookup>
</xsl:variable>
<xsl:template match="queue:push">
<xsl:variable name="message" select="@message"/>
<xsl:variable name="message-queue" select="@message-queue"/>
<xsl:sequence select="func:queue-push($current-context, $message-queue, $message)"/>
</xsl:template>
<xsl:function name="func:queue-push">
<xsl:param name="current-context" />
<xsl:param name="message-queue" as="xs:string"/>
<xsl:param name="message" as="xs:string"/>
<xsl:variable name="guid" select="string(guid:NewGuid())"/>
<xsl:variable name="response">
<xsl:sequence select="queue-manager:Push($current-context, $message-queue, concat($guid, ':', $message))"/>
</xsl:variable>
<response>
<xsl:apply-templates select="$response" mode="generate-human-readable-response">
<xsl:with-param name="message-id" select="$guid"/>
</xsl:apply-templates>
</response>
</xsl:function>
<xsl:template match="text()" mode="generate-human-readable-response">
<xsl:param name="message-id"/>
<xsl:variable name="message" select="$response-output//lookup:message[@response-code = current()]"/>
<message response-code="{.}" message-id="{$message-id}">
<xsl:value-of select="$message/lookup:human-readable"/>
</message>
</xsl:template>
</xsl:transform>
… in which you can bring it together with something as simple as,
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/service/transform/controller/message-queue/base.xslt"?>
<service:operation xmlns:service="http://xameleon.org/service" xmlns:operation="http://xameleon.org/service/operation" xmlns:queue="http://xameleon.org/service/queue">
<operation:queue>
<queue:push message-queue="foo" message="bar"/>
</operation:queue>
</service:operation>
… to produce,
<?xml version="1.0" encoding="UTF-8"?>
<response xmlns="http://nuxleus.com/message/response">
<message response-code="message sent" message-id="924ade3c-315a-4577-8c89-75edbd77cf83">Message was sent successfully!</message>
</response>
The Breakdown
While this is an oversimplified example, it seemed better to keep things simple for purpose of demonstration. No doubt that if the above (or what follows) makes sense to you, you’ll know where to take things from here :)
—
In the above XSLT 2.0 file, the namespace declaration xmlns:queue-manager="clitype:Xameleon.Function.QueueManager?partialname=Xameleon" represents a reference to the QueueManager object written in C#. In this particular case it’s a static class which enables us to access the underlying methods directly w/o first having to create an instance of the QueueManager object due to the fact that all members of a static class are also static. That said, in the true spirit of OOP, we could have just as easily created a non-static class and used queue-manager:new() to create a new instance of that object, wrapping it inside of a variable (e.g. <xsl:variable name="qm" select="queue-manager:new()"/>) to then use that variable as the first value in a call to any of its methods (e.g. queue-manager:Push($qm, $current-context, $message-queue, concat($guid, ':', $message)). I’ll let you decide which usage pattern you prefer (You’re welcome! :D).
With the above in mind, here’s the sequence of events,
The XML sequence file, when applied to the XSLT 2.0 file, is caught by the first template/rule <xsl:template match="queue:push"> (NOTE: It’s actually first caught by the service:operation and operation:queue templates which are not shown here, but both of these templates apply-templates to the underlying node-set after doing some more complex computations unrelated to this example, so I left them out to keep things simple) which in turn takes the values of the attributes @message and @message-queue and passes them to the function 'queue-push' via func:queue-push($current-context, $message-queue, $message). (NOTE: $current-context is the current ASP.NET request context object passed into the transformation via a param. This allows us to extract information related to the underlying HTTP request.) The queue-push function itself is really just a wrapper around our call to queue-manager:Push, and in this particular case it would have been just as easy to call it directly as it would have been to call the wrapper function. But this is primarily due to the oversimplification of this example. In *most* cases, the ability to create complex functions which can be invoked inline to an XPath far outweighs the cost of using a wrapper function to invoke the underlying system call. But as usual, when to use what is answered by: It depends. :)
Moving forward: The call to the queue-manager:Push extension function is converted to a sequence via <xsl:sequence select="queue-manager:Push($current-context, $message-queue, concat($guid, ':', $message))"/>, and the resulting sequence passed on down to the awaiting templates via xsl:apply-templates (along with some parameter values). In our oversimplified example, the first and only match is,
<xsl:template match="text()" mode="generate-human-readable-response">
… who’s primary purpose is to take the result of our call to the message-queue, compare the response to our lookup table, and weave into the output various bits of information that will enable the recipient of the message the ability to better decipher the result of the call to our message queue service, thus weaving AOP into our collective acronymic function from the title.
The end result?
A truly composable language featuring all of the goodness that comes from each item in our collection, all wrapped up into a manageable, queryable, and easily maintainable code base.
Hooray! :D
Questions?


I like composable but the angle brackets still freak me out. But, hey, I have no problem with __double__ __underscores__ so what do I know ;-)
Scala is a nice mix of OO, FP and with mixin traits can be very Aspecty.
@Dan,
>> Scala is a nice mix of OO, FP and with mixin traits can be very Aspecty
On the flip-side (speaking from a platform perspective), F# provides a lot of the same features/functionality as well. Of course, there's no reason you couldn't write an extension function in F# to then call that function from [pick your poison .NET-accessible] language, including (and in particular to this post) XSLT 2.0 which adds nicely to the composability layer.
All good things! :D
F# and the DLR are almost enough to make me flip sides ;-)
Jim Hugunin's recent posts on the DLR have been fascinating.
David, yes, I should have mentioned that XSLT and XPath are composable languages (says so right in the XPath spec), which is probably where I got the idea from. But, I'm trying to go beyond XML, XSLT, & XPath and mix various languages, in the same "class" (aka the language's minimum structure), and have each one do what it does best. So, something like, using C#, F# and Ruby to create one "class". I can't see a compelling reason why we restrict ourselves to one language at a time. Which, I guess is really polyglot programming, but to the extreme.
@Dan,
>> F# and the DLR are almost enough to make me flip sides ;-)
Throw IKVM.NET into the mix and you get all the benefits of both worlds :D
@Don,
>> David, yes, I should have mentioned that XSLT and XPath are composable languages (says so right in the XPath spec), which is probably where I got the idea from.
Not necessarily (meaning where you got the idea...). While they are both composable languages, that's not exactly what most people highlight as their primary strength.
>> But, I'm trying to go beyond XML, XSLT, & XPath and mix various languages, in the same "class" (aka the language's minimum structure), and have each one do what it does best. So, something like, using C#, F# and Ruby to create one "class". I can't see a compelling reason why we restrict ourselves to one language at a time. Which, I guess is really polyglot programming, but to the extreme.
Oh, I absolutely agree! Between 70% of the code I write these days is C#, about 5% (though increasing fairly dramatically) is F#, about 5% in either Ruby or Python (via Ruby.NET, IronRuby, and IronPython), and the remaining 20% in XML and XSLT.
However, the XML/XSLT portion is primarily glue for all of the rest. In other words, a simple way to create logical blocks of code that bind together external components into reusable, service-oriented workflow's. But that's primarily because I prefer XSLT over most any other language, which I realize I am in the minority on. This same basic functionality can easily be replicated in a plethora of languages. *ESPECIALLY* Ruby, which facilitates a nice foundation for the creation of DSL's (e.g. Ruby on Rails)
Of course, I can't get enough of LINQ, and the introduction of expression trees in C# 3.0 has had me drooling ever since Anders provided a high level demo at the Microsoft Technology Summit last month. Talk about composability! :D
This is an oversimplified example ? Geez, I'd hate to see a complicated one.
I think my real problem with all of the XML based languages is the amount of noise that's required to get things done makes it almost impossible for the casual reader to get any idea what's actually going on. Based on this example, XSLT makes Perl look like sweet poetry.
I'm no Ruby bigot (in fact my favourite language is probably Perl), but it would be interesting to compare doing this same job with Ruby to see if it was more readable to lay-people. (Although given that I got lost with even the English version of what this was trying to do, perhaps not.)
@MattMan,
>> I think my real problem with all of the XML based languages is the amount of noise that's required to get things done makes it almost impossible for the casual reader to get any idea what's actually going on.
It's a lot easier to read when you have things inside your favorite XML editor of choice, though I'll be the first to admit that XSLT isn't the easiest of languages to grok, regardless of the what tools you might have at your disposable.
>> Based on this example, XSLT makes Perl look like sweet poetry.
:D :D :D
>> I'm no Ruby bigot (in fact my favourite language is probably Perl), but it would be interesting to compare doing this same job with Ruby to see if it was more readable to lay-people. (Although given that I got lost with even the English version of what this was trying to do, perhaps not.)
The only language I think that could properly mimic this same general idea would be Lisp/Scheme/DSSSL, the latter being the foundation upon which XSLT is built upon (replace angle brackets with parenthesis and you have, for the most part, DSSSL (see: http://www.jclark.com/dsssl/ for more detail), DSSSL being built upon Scheme, which in turn is built upon Lisp.
That said, Ruby has a lot of Lisp'isms built into the language, so it wouldn't surprise me if you could pull together something similar in Ruby. Would have to think it through a bit, but it would be an interesting challenge to see what could become of it.
I'll think it through and see what I can come up with.