From kshaw at kendallshaw.com Fri Sep 15 01:30:46 2017 From: kshaw at kendallshaw.com (Kendall Shaw) Date: Fri, 15 Sep 2017 01:30:46 -0700 Subject: [xquery-talk] tail recursive identity transformation Message-ID: <9a1c5dc7-42ba-08ec-ba97-38a6e3938da5@kendallshaw.com> 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 From mike at saxonica.com Fri Sep 15 02:23:49 2017 From: mike at saxonica.com (Michael Kay) Date: Fri, 15 Sep 2017 10:23:49 +0100 Subject: [xquery-talk] tail recursive identity transformation In-Reply-To: <9a1c5dc7-42ba-08ec-ba97-38a6e3938da5@kendallshaw.com> References: <9a1c5dc7-42ba-08ec-ba97-38a6e3938da5@kendallshaw.com> Message-ID: 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 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 From kshaw at kendallshaw.com Fri Sep 15 03:55:24 2017 From: kshaw at kendallshaw.com (Kendall Shaw) Date: Fri, 15 Sep 2017 03:55:24 -0700 Subject: [xquery-talk] tail recursive identity transformation In-Reply-To: References: <9a1c5dc7-42ba-08ec-ba97-38a6e3938da5@kendallshaw.com> Message-ID: <13543b6d-2120-60f3-daa9-23a2134c78e0@kendallshaw.com> 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 Shaw 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 > > From mike at saxonica.com Fri Sep 15 04:10:08 2017 From: mike at saxonica.com (Michael Kay) Date: Fri, 15 Sep 2017 12:10:08 +0100 Subject: [xquery-talk] tail recursive identity transformation In-Reply-To: <13543b6d-2120-60f3-daa9-23a2134c78e0@kendallshaw.com> References: <9a1c5dc7-42ba-08ec-ba97-38a6e3938da5@kendallshaw.com> <13543b6d-2120-60f3-daa9-23a2134c78e0@kendallshaw.com> Message-ID: > > 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 From John.Snelson at marklogic.com Fri Sep 15 04:23:08 2017 From: John.Snelson at marklogic.com (John Snelson) Date: Fri, 15 Sep 2017 11:23:08 +0000 Subject: [xquery-talk] tail recursive identity transformation In-Reply-To: <13543b6d-2120-60f3-daa9-23a2134c78e0@kendallshaw.com> References: <9a1c5dc7-42ba-08ec-ba97-38a6e3938da5@kendallshaw.com> <13543b6d-2120-60f3-daa9-23a2134c78e0@kendallshaw.com> Message-ID: <9ef429a7-096f-92c1-fe85-80c705e89bb0@marklogic.com> 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 Shaw 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