Re: Formal equivalents using fold-left

Perhaps a better approach is to go directly to a head-tail recursive definition with an auxilary function:

declare function local:filter($input as item()*, $predicate as ..., $position as xs:integer) {
  if (empty($input))
  then ()
  else (if ($predicate(head($input), $position)) {head($input)},
           local:filter(tail($input), $position + 1)
          )
};
declare function fn:filter($input as item()*, $predicate as ...) {
    local:filter($input, 1)
};

> On 12 Mar 2025, at 09:57, Michael Kay <mike@saxonica.com> wrote:
> 
> Many functions with callbacks, such as filter() and for-each() have a formal equivalent using fold-left(), which in turn is defined in terms of recursion.
> 
> Dropping the position argument from the fold-left callback means these need to be rewritten.
> 
> In most case it's easy enough, for example fn:filter becomes
> 
> fold-left($input ! {'item': ., 'pos': position()}, 
>           (), 
>           fn($result, $pair) {
>             if ($predicate($pair?item, $pair?pos))
>             then ($result, $pair?item)
>             else $result
>           })   
> 
> There's the slight disadvantage that this introduces a dependency on "!" and "position()", which are themselves specified rather informally.
> 
> Also, the same technique doesn't work for array functions like array:filter(), because we don't have a simple mapping operator for arrays.
> 
> If we want to reduce the number of primitives that we depend on, then defining numbered-items() (for sequences), and numbered-members() (for arrays) as primitives, using a recursive function for the formal equivalent, would seem to be the best way forward. The question then is whether to make these user-visible functions, or to use them for exposiition only,.
> 
> Michael Kay 
> 
> 

Received on Wednesday, 12 March 2025 11:05:03 UTC