Re: Deep map replacements

Indeed there is a need for such a function; the challenge is writing a specification that does the job. I've made several attempts at this and none of them have been wholly convincing. 

The simplest would probably be something that works as a combination of map:find() and (the proposed) map:substitute(). Say

map:find-and-replace($map, $key, function($key, $value))

which finds matching entries using the same logic as map:find(), and changes their content using the same logic as map:substitute() - that is, it's able to set a new value based on knowing the key and the old value.

A more flexible approach would be allow both map:find and map:find-and-replace to select entries based on a predicate, rather than just an exact match on the key. But even that's not really flexible enough because it doesn't allow you to replace an entry based on looking at its "siblings" or "ancestors". For that I think we probably have to try and find solutions in the XSLT space using recursive xsl:apply-templates and tunnel parameters.

Perhaps a half-way-house would be map:find-and-replace as above, but allowing the $key to be omitted, in which all entries at any depth are passed to the action function, which can either change the value or leave it unchanged as it chooses.

Another candidate would be a "deep filter" which is like (the proposed) map:filter but searches at any depth (following the map:find rules) and returns a flat map containing the selected key-value pairs.

Incidentally, implementation is a challenge even once you have a clear specification, but that's a different problem.

Michael Kay
Saxonica

> On 30 Nov 2020, at 05:15, Joel Kalvesmaki <kalvesmaki@gmail.com> wrote:
> 
> Hi everyone,
> 
> One new standard function I would appreciate having would be a 4arity version of map:put(): map:put($map as map(*),  $key as xs:anyAtomicType, $value as item()* , $apply-deeply as xs:boolean) as map(*). 
> 
> The operation would be the same except with the option of being applied deeply.
> 
> Why? map:put() applies to top-level map entries only, but fn:transform(), which I'm now using extensively, makes a deeper reach desirable. The latter asks for a map with deep maps for static parameters, stylesheet parameters, etc. Often I need to change the parameter options, and therefore the deeper maps, fed to fn:transform() based upon what type of input is being handled. My working version of 4arity map:put() has saved me a lot of time and hassle, and has let me approach the task of building maps for fn:transform() in a modular fashion.
> 
> Originally I thought about  map:replace($map as map(*),  $replacement as map(*) , $apply-deeply as xs:boolean) as map(*) )  Every map entry in $input would be replaced by a top-level map entry in $replacement if the keys match. That's the version that I find most convenient, because I would rather simply build a map, and not have to iterate over each map entry.
> 
> Just an idea, perhaps a bad one.
> 
> jk
> -- 
> Joel Kalvesmaki
> kalvesmaki.com <http://kalvesmaki.com/>

Received on Monday, 30 November 2020 11:10:50 UTC