<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <p>Yes. All Erlang terms, including maps, have a globally defined,
      implementation independent, total order.<br>
    </p>
    The reason, for this "surprising" order of maps, is the alternative
    of using the normal arithmetic order for keys is much worse.<br>
    <br>
    If we want 1 and 1.0 to be different keys (which we do as we use
    matching (=:=) to lookup keys)<br>
    then we need to order 1 and 1.0, and normal arithmetic term ordering
    does not (1 == 1.0).<br>
    <br>
    <br>
    It has been discussed (more and less serious) to expose this
    "map-key-order" with operators like :<, :>, =:<, >:=.<br>
    <br>
    <br>
    /Sverker<br>
    <br>
    <br>
    <div class="moz-cite-prefix">On 10/27/2017 03:13 PM, Ulf Wiger
      wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:CADPRLo-ToDY4w83iGvs1zB3qfiuoDLVr7ZbVqYCtgG1kC7axKw@mail.gmail.com">
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      <div dir="ltr">Actually, that's roughly what I started out
        assuming too, but it's not sufficient. Consider:
        <div><br>
        </div>
        <div>
          <div>1> lists:sort([#{[-1.0] => 0}, #{[1] => 0}]).</div>
          <div>[#{[1] => 0},#{[-1.0] => 0}]</div>
        </div>
        <div><br>
        </div>
        <div>You must dig into each structure and find occurrences of
          floats to determine whether they affect the ordering.</div>
        <div><br>
        </div>
        <div>But yes, the documented sort order should be stable across
          versions. This means, in practice, that it's safe to rely on
          the sorting properties of maps.</div>
        <div><br>
        </div>
        <div>BR,</div>
        <div>Ulf</div>
      </div>
      <div class="gmail_extra"><br>
        <div class="gmail_quote">2017-10-27 10:49 GMT+02:00 Richard
          Carlsson <span dir="ltr"><<a
              href="mailto:carlsson.richard@gmail.com" target="_blank"
              moz-do-not-send="true">carlsson.richard@gmail.com</a>></span>:<br>
          <blockquote class="gmail_quote" style="margin:0 0 0
            .8ex;border-left:1px #ccc solid;padding-left:1ex">
            <div dir="ltr">My interpretation of the reference manual is
              that maps compare to each other like the tuples created by
              this transformation:
              <div><br>
              </div>
              <div>t(Map) -></div>
              <div>    {Ks,Vs} = lists:unzip(lists:keysort(1, [{{if
                is_integer(K) -> 0; is_float(K) -> 1; true -> 2
                end, K}, V} || {K,V} <- maps:to_list(M)])),</div>
              <div>    list_to_tuple(Ks ++ Vs).<br>
              </div>
              <div><br>
              </div>
              <div>For example:</div>
              <div><br>
              </div>
              <div><font face="monospace, monospace">    t(#{65 =>
                  "A", 2.71 => e, 1.0e308 => alot, pi => 3.14,
                  [] => 0})</font></div>
              <div><br>
              </div>
              <div>yields</div>
              <div><br>
              </div>
              <div>
                <div><font face="monospace, monospace">    {{0,65},
                    {1,2.71}, {1,1.0e308}, {2,pi}, {2,[]},</font></div>
                <div><font face="monospace, monospace">        "A",   
                    e,        alot,        3.14,   0}</font></div>
              </div>
              <div><br>
              </div>
              <div>Which:</div>
              <div>1) should be independent of the underlying
                implementation and choice of hash function, and thus
                stable across future versions of Erlang;</div>
              <div>2) is cumbersome to express using the normal term
                order over the basic data types, since float keys always
                sort higher than integers (not really following the rule
                of least surprise).</div>
              <span class="HOEnZb"><font color="#888888">
                  <div><br>
                  </div>
                  <div><br>
                  </div>
                  <div><br>
                  </div>
                </font></span></div>
            <div class="gmail_extra"><span class="HOEnZb"><font
                  color="#888888"><br clear="all">
                  <div>
                    <div class="m_-3576336282511749221gmail_signature"
                      data-smartmail="gmail_signature"><br>
                              /Richard</div>
                  </div>
                  <br>
                </font></span>
              <div class="gmail_quote"><span class="">2017-10-27 9:25
                  GMT+02:00 Ulf Wiger <span dir="ltr"><<a
                      href="mailto:ulf@wiger.net" target="_blank"
                      moz-do-not-send="true">ulf@wiger.net</a>></span>:<br>
                </span>
                <div>
                  <div class="h5">
                    <blockquote class="gmail_quote" style="margin:0 0 0
                      .8ex;border-left:1px #ccc solid;padding-left:1ex">
                      <div dir="ltr">Actually, they ARE, in some ways.
                        <div><br>
                        </div>
                        <div>I should have been clearer. I was, of
                          course, referring to the uses of records where
                          they were never optimal in the first place,
                          but were tolerated e.g. because of the great
                          convenience of referencing elements by name in
                          pattern-matching.<br>
                        </div>
                        <div><br>
                        </div>
                        <div>Quoted from EEP-0043:</div>
                        <div><br>
                        </div>
                        <div>«The idea was a data-type, a syntax-aware
                          mapping of key-value associations with pattern
                          matching. A syntax similar to records but
                          without the hassle of compile-time dependency
                          and with arbitrary terms as keys. Order was
                          not important and it could be implemented with
                          a Hash-Array-Mapped-Trie with good performance
                          and memory trade-offs. This was a different
                          approach than to replace records. It was meant
                          to replace records where suitable and in other
                          regards not be a replacement but its own
                          _thing_.»</div>
                        <div><br>
                        </div>
                        <div>Further, relevant to this discussion:</div>
                        <div><br>
                        </div>
                        <div>«A restriction set on the implementation by
                          the Erlang specification is that order is
                          total, i.e. satisfies _antisymmetry,
                          transitivity and totality_.</div>
                        <div>...</div>
                        <div>- Ordered maps impose restrictions on the
                          underlying implementation and a hashing
                          approach will be nearly impossible.</div>
                        <div>- The underlying structure does not need to
                          be sorted, an order could be produced when
                          needed,»</div>
                        <div><br>
                        </div>
                        <div>The thing I tried to highlight was that "an
                          order could be produced when needed" is
                          actually a bit more involved than you'd think,
                          given that no API function does it for you. At
                          least if you want to reflect the internal sort
                          order - given that the actual implementation
                          is NOT as described in the EEP: "If a key or
                          value differs, the order of the respective
                          terms, in Erlang term order".</div>
                        <div><br>
                        </div>
                        <div>You'd have to write your own sort function,
                          in which you visit all elements of complex
                          structures, finding all instances of floats
                          and ensuring that they get the right priority.</div>
                        <div><br>
                        </div>
                        <div>Or... you simply do this:</div>
                        <div><br>
                        </div>
                        <div>lists:sort(fun(A, B) -> #{A => 0}
                          =< #{B => 0} end, maps:to_list(Map))</div>
                        <div><br>
                        </div>
                        <div><br>
                        </div>
                        <div>As evidenced e.g. by Benoit's comment
                          above, I believe lots of people already
                          rely on the order of map elements being IN
                          SOME WAY stable. This is likely a brittle
                          assumption, but one that may - in time - trap
                          the OTP team into having to preserve the
                          current APPARENT order.</div>
                        <div><br>
                        </div>
                        <div>And the apparent order does appear to be
                          sorted, as long as only maps of size =< 32
                          ("flatmaps") are inspected. For larger maps
                          ("hashmaps"), the order of elements returned
                          by maps:to_list/1 indeed appears arbitrary.</div>
                        <div><br>
                        </div>
                        <div>BR,</div>
                        <div>Ulf W</div>
                      </div>
                      <div class="m_-3576336282511749221HOEnZb">
                        <div class="m_-3576336282511749221h5">
                          <div class="gmail_extra"><br>
                            <div class="gmail_quote">2017-10-27 6:01
                              GMT+02:00 zxq9 <span dir="ltr"><<a
                                  href="mailto:zxq9@zxq9.com"
                                  target="_blank" moz-do-not-send="true">zxq9@zxq9.com</a>></span>:<br>
                              <blockquote class="gmail_quote"
                                style="margin:0 0 0 .8ex;border-left:1px
                                #ccc solid;padding-left:1ex">On
                                2017年10月26日 木曜日 21:13:07 Ulf Wiger
                                wrote:<br>
                                > ... to use as a replacement for
                                records.<br>
                                <br>
                                But they are IN NO WAY a replacement for
                                records.<br>
                                <br>
                                -Craig<br>
                                <div
                                  class="m_-3576336282511749221m_-8808523036434140903HOEnZb">
                                  <div
                                    class="m_-3576336282511749221m_-8808523036434140903h5">______________________________<wbr>_________________<br>
                                    erlang-questions mailing list<br>
                                    <a
                                      href="mailto:erlang-questions@erlang.org"
                                      target="_blank"
                                      moz-do-not-send="true">erlang-questions@erlang.org</a><br>
                                    <a
                                      href="http://erlang.org/mailman/listinfo/erlang-questions"
                                      rel="noreferrer" target="_blank"
                                      moz-do-not-send="true">http://erlang.org/mailman/list<wbr>info/erlang-questions</a><br>
                                  </div>
                                </div>
                              </blockquote>
                            </div>
                            <br>
                          </div>
                        </div>
                      </div>
                      <br>
                      ______________________________<wbr>_________________<br>
                      erlang-questions mailing list<br>
                      <a href="mailto:erlang-questions@erlang.org"
                        target="_blank" moz-do-not-send="true">erlang-questions@erlang.org</a><br>
                      <a
                        href="http://erlang.org/mailman/listinfo/erlang-questions"
                        rel="noreferrer" target="_blank"
                        moz-do-not-send="true">http://erlang.org/mailman/list<wbr>info/erlang-questions</a><br>
                      <br>
                    </blockquote>
                  </div>
                </div>
              </div>
              <br>
            </div>
          </blockquote>
        </div>
        <br>
      </div>
      <br>
      <fieldset class="mimeAttachmentHeader"></fieldset>
      <br>
      <pre wrap="">_______________________________________________
erlang-questions mailing list
<a class="moz-txt-link-abbreviated" href="mailto:erlang-questions@erlang.org">erlang-questions@erlang.org</a>
<a class="moz-txt-link-freetext" href="http://erlang.org/mailman/listinfo/erlang-questions">http://erlang.org/mailman/listinfo/erlang-questions</a>
</pre>
    </blockquote>
    <br>
  </body>
</html>