<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">2017-10-27 23:58 GMT+02:00 Fred Hebert <span dir="ltr"><<a href="mailto:mononcqc@ferd.ca" target="_blank">mononcqc@ferd.ca</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span>On 10/27, Richard Carlsson wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">One way to<br>
avoid this situation would be to say that you can't have two keys that<br>
compare equal with == in the same map, just as for an orddict.<br>
</blockquote>
<br></span>
This would, unfortunately, break pattern matching:<br>
<br>
M = #{1 => 1},<br>
case M of<br>
   #{1.0 := _} -> % it is safe to add 1.0 if we match<br>
       M#{1.0 := 2}; % does this crush a value and change the key?<br>
   _ -><br>
       other<br>
end.<br>
<br>
The fourth line here is problematic. Either (1) maps have a special magical pattern matching case where 1.0 and 1 compare equal (which happens nowhere else) and decide whether to replace the key or keep it the same, or (2) you keep current pattern matching semantics and you can't use existing pattern matching to enforce the constraints above.<br></blockquote><div><br></div><div>Yes, you can't change it now that it's in existing code; it would have had to be done when maps were new. But, having slept on the issue, I now think that the current state of things is fine. The keys must be seen as existing on a different level than the values they map to, more part of the structure of the thing, much like the arity of a tuple. As in your example, they are used in matching, where exact equality is the expected behaviour. It is still bothersome for people like Ulf who want to easily generate a list of the key-value pairs in the order that '<' would consider them - but that is a fairly unusual use case and can be fixed by making separate ordering functions accessible (either as a new :< operator or as a regular BIF).</div><div><br></div><div>One thing can be noted: there is no strict need as far as I can see for the key order to be related to any other particular order like < or :< (apart from convenience), as long as there is always a canonical key order independent of underlying implementation. One could hypothetically use lexicographical order on the stringified keys, and it would work just as well, since the ordering is really only used for deciding which maps are at all comparable. It does decide the ordering of maps of the same size and with different keys (in which case the values are never examined), but if that by necessity must be different from the arithmetic order anyway, it doesn't matter much which order it is. The main thing is that it's cheap to compute, and the :< order is as cheap as any.</div><div><br></div><div>But until :< is actually available as an operator or function, poor Ulf will need to emulate it using 0/1/2-tagging like I showed (recursively, as he pointed out). Or write a NIF for performance.</div></div></div></div>