I think the reason is a different one - it is related to the precise semantics of the group by clause.

The group by clause maps each group of input tuples with equal grouping key(s) to a single output tuple, in which
- the grouping variable(s) is/are bound to the key values (as you would expect)
- all other variables are bound to the concatenated sequence of values bound to the variable name in the members of the group (which may cause surprises)

So when a group has, say, 3 members, the variable $organisations is not any more bound to a single function item, but to a sequence of 3 function items (which are identical). Of course, a sequence of more than one function item cannot be called - only a single function item can be called. In order to check that this is the correct interpretation of the issue, you can remove the second assignment to $organisations, and append to the invocation the predicate [1] - then it works, as then you have again a single function item:

<country>{$country/@name, $organizations[1]($country)}</country>

One way to handle this in a more straightforward way is to shift the function item into an additional, outer FLWOR level at the beginning. While we are at it, let's shift both function items:

let $organizations := function($country){
    $doc//organization[members/@country = $country/@id]/@abbrev/string(.)}
let $membershipPotentcy := function($orgs){
    if (count($orgs)le 0) then 'none'  else if (count($orgs) le 5) then 'few' else 'many'}
return
  element Memberships {
    for $countries in $doc//country
    group by $mp:= $membershipPotentcy($organizations($countries))
    order by $mp
    return
      element {$mp} {
        for $country in $countries
        return
          <country>{$country/@name, $organizations($country)}</country>
      }}


Am Montag, 19. Dezember 2022 um 22:58:30 MEZ hat Graydon <graydonish@gmail.com> Folgendes geschrieben:


On Mon, Dec 19, 2022 at 10:43:25PM +0100, Leo Studer scripsit:

> In the code below I encounter the problem, that I have to define the same xPath function variable $organizations twice and I do not understand why.


In line 10, you've used a let clause to bind a variable of type function to the name organizations.  That's in context a specific FLOWR expression.

The expression in the return clause of that FLOWR expression returns an
element constructor where the contents expression contains another FLOWR
expression.  The first definition on line 10 will be out of scope in
there.

You could define the function with scope for the module:

declare function local:getOrganizations($in as element(country))
    as xs:string* {
  let $thisCountry as xs:string := $in/@id/string();
  return $doc//organization[members/@country = $thisCountry]/@abbrev/string(.)
};

And then use it in both places with the single definition.


--
Graydon Saunders  | graydonish@gmail.com
Þæs oferéode, ðisses swá mæg.
-- Deor  ("That passed, so may this.")