[XML-DEV Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Declarative programming requires a different mindset

  • From: "Costello, Roger L." <costello@mitre.org>
  • To: "xml-dev@lists.xml.org" <xml-dev@lists.xml.org>
  • Date: Sun, 14 Mar 2010 15:24:12 -0400

Declarative programming requires a different mindset
Hi Folks,

I learned imperative programming in school. Learning to write programs declaratively has been a slow process for me. 

I'd like to share with you some exciting, fundamental insights that I've had recently. Thanks to Mary Holstege, Markus Pilman, and Michael Kay for expanding my mind. I invite you to describe your insights into declarative programming.


First, distinguish between imperative and declarative programming:

    Imperative: specify how to do it; prescriptive.

    Declarative: specify what you want; descriptive.

Imperative programming is like a recipe: do this first, then that second, and so forth. Statement A must be executed before statement B.

In declarative programming "before" and "after" are meaningless. Statements can be executed in any order, even in parallel.

Below I examine two examples that illustrate--in a rather dramatic fashion--the differences between imperative and declarative programming.

EXAMPLE #1

Consider this XML document that contains the name and favorite color of members of a fitness center:

<FitnessCenter>
    <Member id="1">
        <Name>Jeff</Name>
        <FavoriteColor>lightgrey</FavoriteColor>
    </Member>
    <Member id="2">
        <Name>David</Name>
        <FavoriteColor>lightblue</FavoriteColor>
    </Member>
    <Member id="3">
        <Name>Roger</Name>
        <FavoriteColor>lightyellow</FavoriteColor>
    </Member>
</FitnessCenter>

Note that each member has an id attribute.

I want to change the document so that each member is identified by his name. I want to change this:

    <Member id="1">
        <Name>Jeff</Name>
        <FavoriteColor>lightgrey</FavoriteColor>
    </Member>

to this:

    <Member id="Jeff">
        <FavoriteColor>lightgrey</FavoriteColor>
    </Member>


Here's some pseudo code that shows how to accomplish this:

For each <Member> element:
   1. replace @id with the value of <Name>
   2. delete <Name>


Here are some key things to note:

A. In my preamble I said "... pseudo code that shows how to ..." That's prescriptive.

B. There is a definite order of actions -- delete <Name> only after extracting its value.

This is all very imperative. Is declarative programming not useful for this application? 

In fact declarative programming is well suited for this application. Let's recast the pseudo-code into the declarative mindset: 

For each <Member> element: 
   The new document has the id attribute's value replaced
   with what was previously the value of the <Name> element, and
   the <Name> element no longer exists.

Here is a key thing to note:

    The new pseudo-code is a description of the new document. 
    It is not a recipe for what actions to take.


Thus, in declarative programming it would be perfectly fine to "delete <Name>" first!

For each <Member> element:
   1. delete <Name>
   2. replace @id with the value of <Name>

In an imperative mindset, this would be nonsensical -- you cannot delete <Name> and then later use it.

In a declarative mindset, it is perfectly fine - you are stating facts about the new document. Order is irrelevant.


EXAMPLE #2

Consider this new version of the fitness center, where some members have a record of their Body Mass Index (BMI):

<FitnessCenter>
    <Member id="1">
        <Name>Jeff</Name>
        <FavoriteColor>lightgrey</FavoriteColor>
        <BMI-Values>
            <BMI date="2009-10-01">36</BMI>
            <BMI date="2009-12-01">32</BMI>
        </BMI-Values>
    </Member>
    <Member id="2">
        <Name>David</Name>
        <FavoriteColor>lightblue</FavoriteColor>
        <BMI-Values>
            <BMI date="2010-01-04">25</BMI>
        </BMI-Values>
    </Member>
    <Member id="3">
        <Name>Roger</Name>
        <FavoriteColor>lightyellow</FavoriteColor>
    </Member>
</FitnessCenter>

Note that each <BMI> element is nested within a <BMI-Values> element.

I want to insert this <BMI> element into the Roger member:

    <BMI date='2010-01-01'>10</BMI>

The imperative approach would be to execute this sequence of actions:

1. If there is no <BMI-Values> element then add one.

2. Insert the new <BMI> element into the <BMI-Values> element.

That approach won't work for declarative programming. Express it declaratively and you can see why:

   In the new document the <Member> will have a <BMI-Values>
   element if it didn't already. The new <BMI> element
   will be nested within the <BMI-Values> element.

Look at this <Member> element:

    <Member level="platinum">
        <Name>Roger</Name>
        <FavoriteColor>lightyellow</FavoriteColor>
    </Member>

How can we declare that in the new document the <BMI> element will be nested within the <BMI-Values> element, since there is no <BMI-Values> element? We can't.

The lesson learned in this second example is:

    In declarative programming you cannot build 
    on top of previous actions.

The declarative approach to this example is:

   The new document has nested within the <Member> element a
   new <BMI-Values> element (and nested within it the new <BMI>
   element), where the <Member> element previously had no
   <BMI-Values> element. Where the <Member> element did previously
   have a <BMI-Values> element, the new document has nested within
   it the new <BMI> element. 


Declarative programming rocks!

/Roger


P.S. XQuery and XQuery Update are declarative programming languages. Below I show how to express the above examples in the XQuery Update language.

EXAMPLE #1

let $source := doc('FitnessCenter.xml')

for $i in $source//Member return
    (
        delete node $i/Name,
        replace node $i/@id with 
            attribute {'id'} {data($i/Name)}
    )

EXAMPLE #2

declare namespace ex = "http://www.example.org";

declare variable $source := doc('FitnessCenter.xml');

declare updating function ex:insert-BMI ($person, $BMI)
{
    if (empty($person/BMI-Values)) then
        insert node <BMI-Values>{$BMI}</BMI-Values> as last into $person
    else 
        insert node $BMI as last into $person/BMI-Values
};


ex:insert-BMI($source//Member[3], <BMI date='2010-01-01'>10</BMI>)





[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index]


PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
 

Stylus Studio has published XML-DEV in RSS and ATOM formats, enabling users to easily subcribe to the list from their preferred news reader application.


Stylus Studio Sponsored Links are added links designed to provide related and additional information to the visitors of this website. they were not included by the author in the initial post. To view the content without the Sponsor Links please click here.

Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.