[Bug 10555] New: Pattern matching proposal for XQuery

http://www.w3.org/Bugs/Public/show_bug.cgi?id=10555

           Summary: Pattern matching proposal for XQuery
           Product: XPath / XQuery / XSLT
           Version: Working drafts
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: XQuery 1.1
        AssignedTo: john.snelson@marklogic.com
        ReportedBy: int19h@gmail.com
         QAContact: public-qt-comments@w3.org


I propose to add a facility to XQuery to enable simple pattern matching, along
the lines of XSLT template patterns, but in a more localized way (i.e. no loose
"dynamic dispatch" as in XSLT). More specifically, I propose to add a new kind
of expression, "match", with syntax similar to the existing "switch" statement,
but with expressions in cases replaced by XPath patterns. An example:

    match ($animal)
    case (foo) return 1
    case (foo/bar) return 2
    case (*[@baz]//text()) return 3
    default return 4

Syntax for patterns, as well as semantics of what, precisely, it means to match
a pattern, can be taken almost verbatim from XSLT 2.1 spec; the only adjustment
that is clearly needed is to remove key(). Some other advanced pattern kinds
might also be trimmed to keep things simple.

Similarly to "switch", matching is done in the order, so the first case that
matches wins - this allows to start with more specific patterns, and generalize
towards the end.

As described, this already matches the expressivity provided by XSLT 1.0 -
"xsl:apply-templates" can be recast as a self-recursive function consisting of
a single "match", with a "case" for every template. The following is an example
taken from XSLT 1.0 Recommendation
(http://www.w3.org/TR/xslt#section-Document-Example), and translated to a
"match":

    declare function local:apply-templates($nodes)
    {
        for $n in $nodes 
        let $apply-templates := function() { local:apply-templates($n/node()) }
        return match ($n)
        case (doc) return
            <html>
                <head>
                    <title>{$n/$title}</title>
               </head>
                <body>
                    {$apply-templates()}
                </body>
            </html>

        case (doc/title) return
            <h1>{$apply-templates()}</h1>

        case (chapter/title) return
            <h2>{$apply-templates()}</h2>

        case (section/title) return
            <h3>{$apply-templates()}</h3>

        case (para) return
            <p>{$apply-templates()}</p>

        case (note) return
            <p class="note">
                <b>NOTE: </b>
                {$apply-templates()}
            </p>

        case (emph) return
            <em>{$apply-templates()}</em>

        (: XSLT built-in template rules :)

        case (text() | @*) return
            text {$n}

        default return
            $apply-templates()
    }

XSLT-like priorities and modes are straightforward to build on top of that
using existing facilities, and it is even possible to implement "xsl:import"
and "xsl:apply-imports" in terms of higher-order functions.

An interesting step further would be to also add "next-match()" as a function.
That would probably necessitate adding another item to the dynamic context
(representing the continuation of the current match within a case).

-- 
Configure bugmail: http://www.w3.org/Bugs/Public/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the QA contact for the bug.

Received on Monday, 6 September 2010 10:49:43 UTC