[xquery-talk] tail recursive identity transformation

John Snelson John.Snelson at marklogic.com
Fri Sep 15 04:23:08 PDT 2017


I don't think you can do a tail recursive tree walk of an XDM tree - you 
at least need a stack of the path taken to a particular node in order to 
process first it's children, and then it's following siblings. You could 
track the stack as an accumulating argument to the recursive call, but 
it may just be easier and more readable to use the function call stack.

Additionally when constructing a result tree, I think most XQuery 
implementations will need to generate an "end tag" after the recursive 
call - which will mean the recursive call won't be at the "tail" at all. 
It's probably possible to optimize this case specifically - but again it 
will entail the implementation keeping track of constructed elements 
that still need to be closed in some kind of stack.

John

On 15/09/17 11:55, Kendall Shaw wrote:
> I was trying to do something like:
>
>   def id(e: List[Int], acc: List[Int]): List[Int] =
>     if (e.isEmpty)
>       acc.reverse
>     else
>       id(e.tail, e.head :: acc)
>
> or
>
> <xsl:template match="@*|node()">
>   <xsl:copy>
>     <xsl:apply-templates select="@*|node()"/>
>   </xsl:copy>
> </xsl:template>
>
> But, I didn't figure how to pass anything analogous to "head" of an 
> element, or analagous to <xsl:copy/>.
>
> If you can give an example of a tail recursive identity transformation 
> in XQuery that would be helpful to me.
>
> Kendall
>
>
> On 09/15/2017 02:23 AM, Michael Kay wrote:
>> I'm very confused by this. The function body contains two recursive 
>> calls. The one inside the typeswitch is certainly not tail-recursive, 
>> so you're going to get recursion depth equal to the maximum tree 
>> depth. The other call, as far as I can see, merely returns its second 
>> argument unchanged, which seems totally pointless.
>>
>> Michael Kay
>> Saxonica
>>
>>> On 15 Sep 2017, at 09:30, Kendall Shaw <kshaw at kendallshaw.com> wrote:
>>>
>>> I don't remember seeing an xquery function that tries to return it's 
>>> input unchanged.
>>>
>>> Can this be improved:
>>>
>>> declare function local:id($e as element()?, $acc as element()?) as 
>>> element() {
>>>    if (empty($e)) then
>>>      $acc
>>>   else
>>>      local:id(()
>>>              , element {node-name($e)} {
>>>                $e/@*
>>>                , for $node in $e/node()
>>>                  return typeswitch($node)
>>>                           case element() return local:id($node, $acc)
>>>                           default return $node
>>>              })
>>> };
>>>
>>> The idea is that functions that do more than return their input 
>>> could be based on the function, and benefit from tail call 
>>> optimization.
>>>
>>> Kendall
>>>
>>>
>>> _______________________________________________
>>> talk at x-query.com
>>> http://x-query.com/mailman/listinfo/talk
>>
>> _______________________________________________
>> talk at x-query.com
>> http://x-query.com/mailman/listinfo/talk
>>
>>
>
> _______________________________________________
> talk at x-query.com
> http://x-query.com/mailman/listinfo/talk


-- 
John Snelson, Principal Engineer              http://twitter.com/jpcs
MarkLogic Corporation                         http://www.marklogic.com



More information about the talk mailing list