Hi Guiseppe,
unfortunately the example won’t be tail-call optimized as your last statement is not the function call itself but a sequence construction that happens to contain the function call. Your function must be of the form: > f(x) => s(x) if your termination condition is met (i.e. no more books) > f(x) => f(g(x)) Your function is defined (more or less) as something like: > f(x) => s(x) if your termination condition is met (i.e. no more books) > f(x) => something + f(g(x)) So you have to get that something (i.e. the sequence concatenation) part inside your g-function, here’s what I think you might want: Cross-posted as gist for better readability https://gist.github.com/micheee/ef75c9f30449c2de3406182ff2fdce50 <https://gist.github.com/micheee/ef75c9f30449c2de3406182ff2fdce50> > declare variable $bookstore := <bookstore>{ > for $i in 1 to 300000 > return element book { > element name { > "Book " || $i > }, > element price { > 1 > }, > element author { > "Author "|| $i > } > } > } > </bookstore>; > > (:~ > Rolling total of prices > @param $prices, accumulates the book prices. > $prices[$n] contains the sum of prices for $book[position() <= $n] > @param $books sequence of books not yet added to $prices > :) > declare function local:sum($prices, $books) > { > let $book := head($books) (: Get first book in sequence :) > let $prices := if(count($prices) = 0) (: if empty, initialize prices > with first price :) > then ($book/price ) > else ( (: add the current rolling total to the > list of rolling totals :) > (: that’s the concatenation part :) > $prices, > element price { $prices[count($prices)] + $book/price } > ) > return ( > if(count($books) > 1) then > local:sum($prices, tail($books)) (: here's the tail call :) > else $prices > ) > }; > > <prices> > { > local:sum((), $bookstore/book) > } > </prices> You can check if your query is tail-call optimized using the query info panel: > - mark as tail call: local:sum(if(empty($prices_2)) then (hea... Hope this helps! Best from Konstanz Michael > Am 18.02.2019 um 19:12 schrieb Giuseppe G. A. Celano > <cel...@informatik.uni-leipzig.de>: > > Hi Jonathan, > > Thanks for that. However, it returns the same stack overflow error as the > other script, when <book/> are 38000. Encreasing the JVM size does not help > either. > > E-mail: cel...@informatik.uni-leipzig.de > <mailto:cel...@informatik.uni-leipzig.de> > Web site 1: http://asv.informatik.uni-leipzig.de/en/staff/Giuseppe_Celano > <http://asv.informatik.uni-leipzig.de/en/staff/Giuseppe_Celano> > Web site 2: https://sites.google.com/site/giuseppegacelano/ > <https://sites.google.com/site/giuseppegacelano/> > >> On Feb 18, 2019, at 4:51 PM, Jonathan Robie <jonathan.ro...@gmail.com >> <mailto:jonathan.ro...@gmail.com>> wrote: >> >> To make it tail-recursive, make the recursive call the last operation in the >> function. >> >> https://en.wikipedia.org/wiki/Tail_call >> <https://en.wikipedia.org/wiki/Tail_call> >> >> The else() clause is what keeps it from being tail recursive. Something >> like this should work: >> >> declare variable $bookstore := <bookstore> >> <book> >> <name>story</name> >> <price>50.00</price> >> <author>smith</author> >> </book> >> <book> >> <name>history</name> >> <price>150.00</price> >> <author>kelly</author> >> </book> >> <book> >> <name>epic</name> >> <price>300.00</price> >> <author>jones</author> >> </book> >> </bookstore>; >> >> declare function local:sum($books, $sum) >> { >> let $sum := $sum + $books[1]/price >> return ( >> <price>{ $sum }</price>, >> $books[2] ! local:sum(tail($books), $sum) >> ) >> }; >> >> <prices> >> { >> local:sum($bookstore/book, 0) >> } >> </prices> >> >> >> Jonathan >> >> On Mon, Feb 18, 2019 at 10:24 AM Giuseppe G. A. Celano >> <cel...@informatik.uni-leipzig.de <mailto:cel...@informatik.uni-leipzig.de>> >> wrote: >> I am writing a recursive function which is similar to the one here: >> >> https://stackoverflow.com/questions/27702718/to-add-values-in-cumulative-format >> >> <https://stackoverflow.com/questions/27702718/to-add-values-in-cumulative-format> >> >> Interestingly, local:sum() works if there are not many <book/>. However with >> 38000 book element I get the error "Stack Overflow: Try tail recursion". >> >> Any idea? >> >> Ciao, >> Giuseppe >> >> >