XQuery/Timing Fibonacci algorithms

Fibonacci algorithms
Fibonacci is the computer science 'hello world'. A recursive function which follows the definition of the Fibonacci series looks pretty much the same in every language. Here is the XQuery version:

The empty sequence is used here as a return when the function is undefined so the return type is an optional integer. Top-down, goal-oriented, close to the mathematical definition but requiring repeated re-evaluations of intermediate values. So how about bottom-up, starting with the known and working up to the goal?

with a 'front-door' function to get started:

Iterative solutions in which variables are updated look rather messy by comparison with this tail-recursive formulation, a style essential to many algorithms in XQuery.

Timing
Just how much worse is the recursive formulation? We need to time the calls, and now we really could do with those higher order functions so we can pass either fib function to a timer function to execute. Step in eXists function modules. These raise XQuery from an XML query language to a viable web application platform. The util module provides two functions:

* util:function(qname,arity) to create a function template which can be passed to   * util:call (function, params)to evaluate the function

so we can create the recursive function template with:

The timer function takes a function, a sequence of the parameters to be passed to the function and a repetition number. The timing is based on system time and the time difference converted to seconds and then to milliseconds:

and call it as

An intermediate data structure
Calling the timer with n ranging from 1 to max will generate the required data. Rather than simply outputting this data, we need an intermediate XML data structure containing the results. This can then be transformed into different representation or analysed later, to fit a curve to the data perhaps or export to a spreadsheet.

Results as a table
This data structure can be transformed to a table, iterating over the tuples.

};

Here the XPath name function is used to convert from the tag names to strings. This reflection allows very generic functions to be written and is a key technique for making the transition from problem-specific structures to generic functions. Note that the dataset has not been typed. This is because the function is written with minimal requirements of the structure which would require a permissive schema language to express.

Results as a graph
For graphing, this basic matrix could be imported directly into Excel, or, thanks to the wonderful GoogleCharts, to a simple line graph. Selected columns of the dataset are extracted and joined with commas, then all datasets joined with pipes.

The final script
Finally, adding some intro, some page layout and CSS, the final script looks like:

};

declare option exist:serialize "method=xhtml media-type=text/html omit-xml-declaration=no indent=yes        doctype-public=-//W3C//DTD&#160;XHTML&#160;1.0&#160;Transitional//EN        doctype-system=http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd";

let $max := xs:integer(request:get-parameter("max",1)) let $reps := xs:integer(request:get-parameter("reps",1)) let $call-fib-recur := util:function(QName("http://www.cems.uwe.ac.uk/xmlwiki/myfn","myfn:fib-recur"),1) let $call-fib-itr:= util:function(QName("http://www.cems.uwe.ac.uk/xmlwiki/myfn","myfn:fib-itr"),1) let $runs :=