<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE bugzilla SYSTEM "https://www.w3.org/Bugs/Public/page.cgi?id=bugzilla.dtd">

<bugzilla version="5.0.4"
          urlbase="https://www.w3.org/Bugs/Public/"
          
          maintainer="sysbot+bugzilla@w3.org"
>

    <bug>
          <bug_id>24726</bug_id>
          
          <creation_ts>2014-02-19 08:23:47 +0000</creation_ts>
          <short_desc>map:new() and map:merge()</short_desc>
          <delta_ts>2014-05-15 23:35:15 +0000</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>1</classification_id>
          <classification>Unclassified</classification>
          <product>XPath / XQuery / XSLT</product>
          <component>XSLT 3.0</component>
          <version>Working drafts</version>
          <rep_platform>PC</rep_platform>
          <op_sys>Linux</op_sys>
          <bug_status>CLOSED</bug_status>
          <resolution>FIXED</resolution>
          
          
          <bug_file_loc></bug_file_loc>
          <status_whiteboard></status_whiteboard>
          <keywords></keywords>
          <priority>P2</priority>
          <bug_severity>normal</bug_severity>
          <target_milestone>---</target_milestone>
          
          <blocked>24999</blocked>
          <everconfirmed>1</everconfirmed>
          <reporter name="Jonathan Robie">jonathan.robie</reporter>
          <assigned_to name="Michael Kay">mike</assigned_to>
          <cc>abel.braaksma</cc>
          
          <qa_contact name="Mailing list for public feedback on specs from XSL and XML Query WGs">public-qt-comments</qa_contact>

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>100854</commentid>
    <comment_count>0</comment_count>
    <who name="Jonathan Robie">jonathan.robie</who>
    <bug_when>2014-02-19 08:23:47 +0000</bug_when>
    <thetext>XPath can now create empty arrays or create arrays from literals, two of the uses of map:new().  

The third use is to merge arrays - for this purpose it would be helpful to have a more meaningful name.  Consider the following two expressions, which differ only by the name of the function:

$map =&gt; map:new( { &quot;counter&quot; : $map($key) + 1 } )

$map =&gt; map:merge( { &quot;counter&quot; : $map($key) + 1 } )

To my eyes, the meaning is much more obvious with  the name map:merge().

I suggest:

1. Either keep the zero-arity and 1-arity map:new() as is or drop them in favor of the new constructors.

2. Create a new function called map:merge() with the same semantics as the current map:new() with arity greater than 1</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>100891</commentid>
    <comment_count>1</comment_count>
    <who name="Michael Kay">mike</who>
    <bug_when>2014-02-19 13:42:15 +0000</bug_when>
    <thetext>The most recent decision of the joint WGs is that arrays are no longer a specialisation of maps. Presumably, therefore, this bug report is obsolete? At any rate, many of the justifications it uses no longer apply.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>100915</commentid>
    <comment_count>2</comment_count>
    <who name="Jonathan Robie">jonathan.robie</who>
    <bug_when>2014-02-19 17:23:17 +0000</bug_when>
    <thetext>Hi Mike,

I must be exhausted, I don&apos;t know why I said &apos;arrays&apos; when I meant &apos;maps&apos;. Here is the corrected text.

----------------------

XPath can now create empty maps or create maps from literals, two of the uses of map:new().  

The third use is to merge maps - for this purpose it would be helpful to have a more meaningful name.  Consider the following two expressions, which differ only by the name of the function:

$map =&gt; map:new( { &quot;counter&quot; : $map($key) + 1 } )

$map =&gt; map:merge( { &quot;counter&quot; : $map($key) + 1 } )

To my eyes, the meaning is much more obvious with  the name map:merge().

I suggest:

1. Either keep the zero-arity and 1-arity map:new() as is or drop them in favor of the new constructors.

2. Create a new function called map:merge() with the same semantics as the current map:new() with arity greater than 1</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>102211</commentid>
    <comment_count>3</comment_count>
    <who name="Michael Kay">mike</who>
    <bug_when>2014-03-11 17:04:28 +0000</bug_when>
    <thetext>I think it might be a good idea to review where we stand on namespaces for these functions before we review the local names.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>102705</commentid>
    <comment_count>4</comment_count>
    <who name="Michael Kay">mike</who>
    <bug_when>2014-03-20 17:12:09 +0000</bug_when>
    <thetext>The XSL WG telcon looked at this today briefly; we didn&apos;t feel ready to make a decision but there was some sympathy to the idea of keeping the map:new#0 function to create an empty map, and renaming map:new#1 as map:merge#1.

Given that we can also create a new map using the XPath 3.1 syntax map{}, the only real case for keeping map:new#0 is the transitional benefit that it provides a way of creating a map using functions alone, without relying on new syntax. But if the only purpose is transitional, then map:merge(()) (merging an empty set of maps to create an empty map) might be good enough for the requirement.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>104368</commentid>
    <comment_count>5</comment_count>
    <who name="Michael Kay">mike</who>
    <bug_when>2014-04-24 18:57:46 +0000</bug_when>
    <thetext>The WG looked at this today and agreed that it would be a good idea to try and find function names that more closely matched the tasks being performed, however elegant it might appear to have one multi-purpose function. The editor was asked to produce a proposal.

I&apos;m inclined to go with the following:

(1) To create an empty map, use either map{} or map:merge(()).

(2) map:merge() acts lile the current map:new() - it takes a sequence of maps and merges them into a single map, resolving duplicate keys.

(3) To add an entry to a map (creating a new map), use map:put($map, $key, $value). The new entry replaces any existing entry with the same key. This function works well with the new function chaining operator: map{} =&gt; map:put(&quot;a&quot;, 1) =&gt; map:put(&quot;b&quot;, 2) (though of course simple cases like this can be done equally well with a map expression).

(4) map:entry() which creates a singleton map, can now be dropped. Anyone who really wants this function can either use map expressions, or implement it as 

let $map:entry := map:put(map{}, ?, ?)

So we end up with two functions map:merge() replacing map:new(), and map:put() replacing map:entry().</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>104816</commentid>
    <comment_count>6</comment_count>
    <who name="Abel Braaksma">abel.braaksma</who>
    <bug_when>2014-04-30 14:32:32 +0000</bug_when>
    <thetext>I agree to renaming map:merge. Also, allowing map{} makes sense, but it doesn&apos;t require a change, it is already allowed:

MapExpr ::= &quot;map{&quot; (KeyExpr &quot;:&quot; ValueExpr (&quot;,&quot; KeyExpr &quot;:&quot; ValueExpr )*)? &quot;}&quot;

I would prefer to keep map:entry (or perhaps map:item) as the equivalent counterpart of xsl:map-entry (or xsl:map-item).

Note also that we used to have map:put, but don&apos;t have it anymore.

Furthermore, it strikes me as odd that map:put would _not_ throw an error if the item already existed. I would like to argue, in line with existing maps/dictionaries/hashsets in other programming languages, that adding an item that already exists is not allowed. We could consider both a map:put and map:set, where the latter overrides an existing entry, or adds it if it doesn&apos;t exist, and the former (map:put) raises an error if an item exists. Instead of map:put, perhaps map:add is better.

To summarize, I would like:
1) map:add (error if exists)
2) map:put/set (no error if exists, overwrites)
3) map:merge (as per MK&apos;s proposal)
4) map{} (as per MK&apos;s proposal)
5) map:entry (retain it)
6) remove map:new</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>105843</commentid>
    <comment_count>7</comment_count>
    <who name="Michael Kay">mike</who>
    <bug_when>2014-05-13 13:08:04 +0000</bug_when>
    <thetext>The XSL WG looked at this on 8 May 2014. We propose, subject to the XQuery WG concurring, the following:

1. map:new#0 is dropped. An empty map can be constructed using map{}.

2. map:new#1 is renamed map:merge, with no change in behaviour.

3. A new function map:put($map, $key, $value) is defined. The semantics are equivalent to map:merge(($map, map{$key, $value}))</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>105844</commentid>
    <comment_count>8</comment_count>
    <who name="Michael Kay">mike</who>
    <bug_when>2014-05-13 13:12:10 +0000</bug_when>
    <thetext>Item 3 in the previous comment should read:

3. A new function map:put($map, $key, $value) is defined. The semantics are equivalent to map:merge(($map, map{$key : $value}))</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>105845</commentid>
    <comment_count>9</comment_count>
    <who name="Jonathan Robie">jonathan.robie</who>
    <bug_when>2014-05-13 13:15:45 +0000</bug_when>
    <thetext>Looks good to me.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>105858</commentid>
    <comment_count>10</comment_count>
    <who name="Michael Kay">mike</who>
    <bug_when>2014-05-13 15:26:16 +0000</bug_when>
    <thetext>The proposal has been accepted by both XSL WG and XQuery WG and will be implemented in both XSLT 3.0 and F+O 3.1.</thetext>
  </long_desc>
      
      

    </bug>

</bugzilla>