Re: [xquery-talk] tail recursive identity transformation
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 > > > > > > > > But, I didn't figure how to pass anything analogous to "head" of an > element, or analagous to . > > 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 Shawwrote: >>> >>> 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@x-query.com >>> http://x-query.com/mailman/listinfo/talk >> >> ___ >> talk@x-query.com >> http://x-query.com/mailman/listinfo/talk >> >> > > ___ > talk@x-query.com > http://x-query.com/mailman/listinfo/talk -- John Snelson, Principal Engineer http://twitter.com/jpcs MarkLogic Corporation http://www.marklogic.com ___ talk@x-query.com http://x-query.com/mailman/listinfo/talk
Re: [xquery-talk] tail recursive identity transformation
> > If you can give an example of a tail recursive identity transformation in > XQuery that would be helpful to me. > I don't see how it can be possible. It's a task that naturally requires a stack. One could possibly do something very contrived that uses an application-level data structure in place of the stack, but it's not clear what benefits this would bring. Michael Kay Saxonica ___ talk@x-query.com http://x-query.com/mailman/listinfo/talk
Re: [xquery-talk] tail recursive identity transformation
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 But, I didn't figure how to pass anything analogous to "head" of an element, or analagous to . 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 Shawwrote: 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@x-query.com http://x-query.com/mailman/listinfo/talk ___ talk@x-query.com http://x-query.com/mailman/listinfo/talk ___ talk@x-query.com http://x-query.com/mailman/listinfo/talk
Re: [xquery-talk] tail recursive identity transformation
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 Shawwrote: > > 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@x-query.com > http://x-query.com/mailman/listinfo/talk ___ talk@x-query.com http://x-query.com/mailman/listinfo/talk