Help! Can anybody explain this XQuery?

Can anybody explains this part?
if (
for $e3 in $other
return
if ($e3 << $e1) then 1 else ()
) then $e1 else ()
)
Thanks!
THis is the whole function definition:

declare function count-nodes($sequence) {
if ($sequence) then (
let $head := (
for $e1 in $sequence
let $other := (
for $e2 in $sequence
return (
if (not($e1 is $e2)) then $e2 else ()
)
)
return
if (
for $e3 in $other
return
if ($e3 << $e1) then 1 else ()
) then $e1 else ()
) return
let $tail := (
for $e1 in $sequence
return
if (not($e1 is $head)) then $e1 else ()
)
return (1 + count-nodes($tail))
)
else 0
}

I can.

but before I do, let me give some remarks:
I do not know where you got this XQuery from. Either it is a puzzle , or something programmed by an XQuery novice. Judging from the variable names, what is intended to be achieved can be achieved in a much simpler way with XQuery. Besides, the query does not do what the variable names suggest. And it will create a type exception. And it does not conform to XQUery as of teh current spec and Tamino 4.4. implementation. Here we go:

declare function xx:count-nodes($sequence)
{
if ($sequence) then
( let $head := ( for $e1 in $sequence
let $other := ( for $e2 in $sequence
return ( if (not($e1 is $e2)) then $e2
else () ) )
return if ( for $e3 in $other
return if ($e3 << $e1) then 1
else () ) then $e1
else () )
return let $tail := ( for $e1 in $sequence
return if (not($e1 is $head)) then $e1
else () )
return (1 + xx:count-nodes($tail)) )
else 0}

from the name of the function, we can assume that it is intended to
count the nodes in a sequence. The fact that all entries of the sequence
are compared using the “is” operator also implies that the sequence consists of nodes only (otherwise you get a type exception, because the
“is” operation is defined on nodes only.

the outermost if says:
if the incoming sequence is empty, return 0

so for the empty sequence, teh number of nodes is correctly returned.

In case the sequence is not empty:
a variable $head is defined. However, in contrast to its name, it will contain a sequence of all nodes that are not identical to the first node of the sequence (in document order, i.e. not the first entry in the sequence):
This is the reason for this result:

for $e1 in $sequence
let $other := ( for $e2 in $sequence
return ( if (not($e1 is $e2)) then $e2
else () ) )
for each entry i$e1 n the sequence, the variable $other is computed.
it will contain a sequence of all nodes which are not identical to $e1
return if ( for $e3 in $other
return if ($e3 << $e1) then 1
else () )
then $e1
else () )
means that whenever there is a node is before $e1 in document order, the argument of teh if evaluates to true, and $e1 is returned, i.e. , all nodes are returned that have a predecessor in document order in the sequence (not really what is implied by the name $head)

return let $tail := ( for $e1 in $sequence
return if (not($e1 is $head)) then $e1
else () )
will fails because of a type error, whenever the input sequence has more than two different nodes as entries, because then $head is a non-atomic sequence which creates a type error if operator “is” is applied to it.
The intention seems to be: compute all node except the $head one.

As there is a built-in count function, I wonder what the intention of this question to the forum is

Regards

Harald

Thank you very much, Doctor. Your insight was very keen.

This XQuery is excerpted from a technical report “Expressive Power of Recursion and Aggregates in XQuery” which can be found as an attachement or at http://www.adrem.ua.ac.be/pub/TR2005-05.pdf

This function aims to simulate the “count” function using recursion and constructors. Its argument “$sequence” is a sequence of nodes. This example shows that count() can be simulated by recursion and constructors. However its lemma 7 gives the result that count() CANNOT be simulated by recursion itself, given that count() can distinguish two set-equivalent environments while Recursion can’t. I’m a little confused at this. Do you see any example that can exemplify this argument?

And I still have the same stupid question: Look at this paragraph:
if (
for $e3 in $other
return
if ($e3 << $e1) then 1 else ()
) then $e1 else ()

Note that $other may contain multiple nodes. So for each node in $other, if it’s less than $e1 in document order, it would return a 1. Will there be multiple 1s in the outer if argument then? Or there’s only one 1 so that the if clause can be executed because 1 is a literal value?

Please excuse my stupid questions as I’m a novice in XQuery. I look forward to your reply, especially to the first question. Many thanks!
TR2005-05.pdf (337 KB)

Hi,

the paper you ae referring to is definitely not a good choice to learn XQuery.
To answer your second question on:


if ( 
for $e3 in $other 
return 
if ($e3 << $e1) then 1 else () 
) then $e1 else () 

In deed, if there are three nodes before $e1, this is equivalent to


if (( 1, 1, 1)) then $e1 else () 

the effective boolean value of the expression in “if” is “true”, so the result of the expression is $e1.
The effective boolean value is defined as
If its operand is an empty sequence, fn:boolean returns false.

If its operand is a sequence whose first item is a node, fn:boolean returns true.

If its operand is a singleton value of type xs:boolean or derived from xs:boolean, fn:boolean returns the value of its operand unchanged.

If its operand is a singleton value of type xs:string, xdt:untypedAtomic, or a type derived from one of these, fn:boolean returns false if the operand value has zero length; otherwise it returns true.

If its operand is a singleton value of any numeric type or derived from a numeric type, fn:boolean returns false if the operand value is NaN or is numerically equal to zero; otherwise it returns true.

Regards

Harald