The following expressions (which should be interpreted and evaluated identically as far as I know),
$coll//a[contains(., 'str')] => count()
and
count( $coll//a[contains(., 'str')] )
... may, in fact, return different values.
After some investigation I concluded that the difference is due to the fact that element 'a' has a case-insensitive range index defined on it, and the first expression containing the arrow operator fails to use the index, hence the different results.
Similar expressions with a matches(., 'str') filter clause always give identical values.
I expected the two expressions to be evaluated in exactly the same way
This could be a bug. Can you expand your report a bit so we can reproduce this. We need to know how the index is configured, and a sample query (and data) that shows the different results.
This may help you reproduce the bug a little easier:
<debug>
<a>Test</a>
<a>test</a>
</debug>
<collection xmlns="http://exist-db.org/collection-config/1.0">
<index xmlns:xs="http://www.w3.org/2001/XMLSchema">
<range>
<create qname="a" type="xs:string" case="no"/>
</range>
</index>
</collection>
xquery version "3.1";
<debug>
<case nr="1" expected="2" result="{count(doc('debug.xml')//a[contains(.,'test')])}"/>
<case nr="2" expected="2" result="{(doc('debug.xml')//a[contains(.,'test')])=>count()}"/>
</debug>
and the offending result:
<debug>
<case nr="1" expected="2" result="2"/>
<case nr="2" expected="2" result="1"/>
</debug>
Seems to be fixed in 5.3.0 could not be reproduced.
I assume this was fixed by #2470 and #2471
Most helpful comment
This may help you reproduce the bug a little easier:
my XML
index config
xquery
and the offending result: