[xquery-talk] How much laziness is permitted?

Michael Kay mike at saxonica.com
Wed Mar 11 00:39:04 PST 2009

Yes, section 2.3.4 is intended to allow implementations to do as much lazy
evaluation as they like. There is still some debate about edge cases.

As for the interaction with try/catch, the WG is still debating these issues
(the spec is far from finished). I think it's likely that the spec will
allow implementations a lot of freedom, at the cost of some loss of
predictable/interoperable behaviour - that's the way the XQuery WG has
tended to go in the past when such questions arise. The rule that a
processor doesn't have to do extra work solely in order to look for errors
will remain, despite the fact that the errors might be caught at an outer

Michael Kay

> -----Original Message-----
> From: talk-bounces at x-query.com 
> [mailto:talk-bounces at x-query.com] On Behalf Of Pavel Minaev
> Sent: 11 March 2009 00:14
> To: talk at x-query.com
> Subject: [xquery-talk] How much laziness is permitted?
> Re-reading the XQuery spec again, I'm trying to understand 
> the full implications of section 2.3.4 "Errors and 
> Optimization". If I understand it correctly, it at least 
> allows implementation to be fully lazy with respect to 
> sequence, in that they can be implemented as lazy non-cached 
> sequence generators - i.e. akin to Microsoft's LINQ "deferred 
> evaluation", where you can chain and nest query expressions 
> as much as you like, but the whole thing will only start 
> evaluating when you actually try to use the resulting 
> sequence (and only to the extent that you use it), and any 
> errors are similarly only reported at that latter point. 
> However, I would like to confirm that I am indeed correct there.
> Another related question is on how this interacts with 
> try-catch in XQuery 1.1. I've read the corresponding note in 
> the draft in section 3.12, but I'm not sure I fully 
> understand what it means. Consider this
> code:
>   (* module 1 *)
>   declare function m1:gen() {
>       for $x in 1 to 10000 return if ($x lt 10000) then $x 
> else error()
>   }
>   (* module 2 *)
>   declare function m2:trygen() {
>     try { m1:gen() } catch * { () }
>   };
>   (* query *)
>   m2:trygen()[1],
>   let $xs := m2:trygen()
>   for $x in $xs return $x * $x
> Now if the full laziness is still allowed, a legitimate 
> implementation can either return 1 when lazy, or () when not. 
> However, I can't wrap my head about the second expression. If 
> gen() is implemented lazily and returns a generator, then the 
> error will only be triggered on the next line while running 
> it. On the other hand, the spec seems to require that the 
> error should be caught by the catch block in trygen(), since 
> syntactically it appears in gen() when called by trygen(). 
> But how can trygen() do this without either doing eager 
> evaluation, or relying on some form of re-invokable 
> continuations (to backtrack to the proper point of error on 
> exception, and return the correct result?
> I am particularly interested in how to handle this in 
> presence of true separate compilation for modules (i.e. when 
> compiling trygen(), we don't know how it will be used, and 
> when compiling the query, we don't know that trygen() has a 
> try-catch expression inside).
> _______________________________________________
> talk at x-query.com
> http://x-query.com/mailman/listinfo/talk

More information about the talk mailing list