Re: map:group-by or map:build with a sequence of keys?

On 10/17/2022 6:11 PM, Michael Kay wrote:
> It's probably best to put comments against the relevant Git issue. We're trying - with limited success - to keep discussions on different topics separate.
>
> Yes, I did see it, and I see pro's and con's in the idea so I'm sitting on the fence.
>
> (a) Dimitre is pushing for maps to be generalised so a key is a sequence of atomic values (or beyond...), and that's a different semantics for allowing map:build to compute multiple keys each of which is atomic.

I remembered that but as it didn't appear to have a resolution I tried
to consider the suggestions for map:group-by or now map:build based on
the existing map model and see whether they could be improved/generalized.


> (b) The current draft of map:build envisages a call to $key() to compute the key, and a call to $value() to compute the corresponding value. If there were multiple keys, would they all map to the same value? Or would you want to generate multiple key-value pairs from a single item in the input sequence? Which would suggest a single callback producing a composite result; but that starts to feel more like the existing map:merge.
>

My idea and understanding and suggestion is based on the implementation
I included below which computes the same value based on the $value
function parameter and the item in the sequence as the original
suggestion in your pull request. It only uses fold-left on the possible
key sequence, with the map as the accumulator, to recursively add any
key/value pair to the map.

It tries to allow to map an item to possibly more than one group, which
I hoped the example and the implementation (and for the XSLT guys, the
reference to the sample from the XSLT spec) would make clear.

In my view it is just a refinement to justify the statement behind the
original map:group-by, namely that "This function may sometimes be an
effective substitute for the xsl:for-each-group instruction in XSLT.".
Admittedly that statement doesn't appear any longer for map:build but I
continue to think that there is a use case (from that origin) to allow
for a key sequence, easily implemented as suggested below.


>
>>> When map:group-by was introduced I found the restriction of a single key
>>> instead of a sequence of keys unnecessarily restrictive (some people on
>>> Slack agreed), the same appears in my view to be the case for the new
>>> map:build, I think it could be easily adapted to handle a sequence of
>>> keys by using e.g.
>>>
>>>   fold-left($input, map{}, ->($map, $next) {
>>>
>>>    fold-left($key($next), $map, ->($map, $key) {
>>>     let $nextValue := $value($next) return
>>>     if (map:contains($map, $key))
>>>     then map:put($map, $key, $combine($map($key), $nextValue))
>>>     else map:put($map, $key, $nextValue)})
>>>   }
>>> )
>>>
>>> as the implementation body/definition of the result of
>>>
>>> map:build(
>>> $input    as item()*,
>>> $key    as function(item()) as xs:anyAtomicType*    := fn:identity#1,
>>> $value    as function(item()) as item()*    := fn:identity#1,
>>> $combine    as function(item()*, item()*) as item()*    := fn:op(',')
>>> ) as map(*)
>>>
>>>
>>> Use case in my view is the classical example of the XSLT 3 spec where in
>>> e.g.
>>>
>>> <titles>
>>>      <title>A Beginner's Guide to <ix>Java</ix></title>
>>>      <title>Learning <ix>XML</ix></title>
>>>      <title>Using <ix>XML</ix> with <ix>Java</ix></title>
>>> </titles>
>>>
>>> you want to group the "title" elements by the "ix" child elements, with
>>> the proposed change above that would give e.g.
>>>
>>> map {
>>>    "Java": (<title>A Beginner's Guide to <ix>Java</ix>
>>> </title>, <title>Using <ix>XML</ix> with <ix>Java</ix>
>>> </title>),
>>>    "XML": (<title>Learning <ix>XML</ix>
>>> </title>, <title>Using <ix>XML</ix> with <ix>Java</ix>
>>> </title>)
>>> }
>>>
>>>
>>> XSLT 2/3 grouping always had this feature to allow an item in the
>>> grouping population to belong to several groups, the above change would
>>> give that same power to XPath/XQuery based grouping using map:build.
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>

Received on Monday, 17 October 2022 20:39:40 UTC