Thursday, 29 April 2010

MarkLogic: XQuery Function Overloading

I remember seeing in a few places that XQuery doesn't support function overloading. I also remember seeing examples where function overloading is used.

This simplistic example shows overloading at work - as written for MarkLogic (although the example could be easily modified for eXist:

4 comments:

Rouzbeh said...

Yes, it seems that we can overload by number of arguments but not on the "type" of the arguments;
------------------------
xquery version "1.0";
declare namespace xdmp="http://marklogic.com/xdmp";
declare function local:pp($x as xs:integer) {$x+1};
declare function local:pp($x as xs:string) {$x};
local:pp(1)
--------------------------

which is sad, that closes allot of doors - like implementing visitor patterns. Something - to my opinion - very essential for traversing an XML. For that we are stuck with recursive calls to a function with typeswitch. and in worst case the case you want might be the last "case"!
vistor pattern would take care of that for me.

Any suggestion on how to overlaod over types ?!

Thanks

this one gives an error:

Alex Bleasdale said...

Rouzbeh,

Yes - you're right - the error MarkLogic throws is in the spec:

http://www.w3.org/TR/xquery/#ERRXQST0034

As for suggestions regarding overloading over types, the only method I know of right now is the typeswitch case - I'll post an example based on the snippet you sent me if that helps.

chris wallace said...

Hi Alex

Overloading by number of args is still useful even if overloading by type would be even better.

One typical use is for drilling down into detail:

declare function met:area-boundaries() as element(boundaries) {
doc("/db/Wiki/Met/shippingareas.xml")/boundaries
};

declare function met:area-boundary($area as xs:string) as element(boundary) {
met:area-boundaries()/boundary[@area=$area]
};

Another common use is for recursive functions: one function does the set-up , the other does the work with more parameters:

declare function local:fib($n as xs:integer) as xs:integer? {
if ($n < 0) then ()
else if ($n = 0) then 0
else local:fib($n, 0, 1)
};

declare function local:fib($n as xs:integer, $m1 as xs:integer, $m2 as xs:integer) as xs:integer {
if ($n = 1)
then $m2
else local:fib($n - 1,$m2, $m1 + $m2)
};

These examples are from the XQuery Wikibook. BTW it would be great to have ML examples there too where they differ from the eXist examples - better still I think if executable.

Alex Bleasdale said...

Chris,

Thanks - those are great examples. The XQuery wikibook is an excellent resource, by the way! :)