How to write a while loop in MarkLogic XQuery

marklogic, xquery

Solution

Recursion is the usual way. Another is to use a FLWOR with a `try-catch` and throw an exception with a known code to exit early.

try {
  for $x in 1 to count($tokens)
  return tok($x) }
catch ($ex) {
  if ($x/error:code eq 'BREAK') then ()
  else xdmp:rethrow() }

The `tok` function would call `error((), 'BREAK')` to exit the parent FLWOR expression. If needed you could multiply the token count by some factor, or use an arbitrary large number.

https://github.com/robwhitby/xray/blob/coverage/src/coverage.xqy has a more complex example, in the `cover:actual-via-debug` function.

Problem

Is there any recognized idiom for writing the equivalent of a while loop in MarkLogic XQuery? I know that I could write a tail-recursive routine, but MarkLogic XQuery does not optimize tail-recursion and I'm getting a stack overflow (I have to go around my loop ~20000 times). Editorial note: as of MarkLogic 6, tail recursion is optimized in MarkLogic.

Original source