<br><br>On Mon, 13 May, 2013 at 11:15 AM, Joe Armstrong <erlang@gmail.com> wrote:<br>
<blockquote type="cite"><br><br><div class="gmail_quote">On Thu, May 9, 2013 at 10:56 PM, Robert Virding <span dir="ltr"><<a href="mailto:robert.virding@erlang-solutions.com" target="_blank">robert.virding@erlang-solutions.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div style="font-size:12pt;font-family:times new roman,new york,times,serif">Even before taking a really deep dive into studying the EEP one thing I can immediately say: get rid of this having both <i>equal</i> and <i>match</i> and <b>USE ONLY MATCH. </b>Keys are the same when they match. Period. This paragraph:<br>
<br>If key <code>K</code> does not <em>equal</em> any existing key in the map, a new association
will be created from key <code>K</code> to value <code>V</code>. If key <code>K</code> is <em>equal</em> to an existing
key in map <code>M</code> its associated value will be replaced by the new value <code>V</code> <em>and</em>
the new key <code>K</code> will replace the old key if the key does not <em>match</em>. In both
cases the evaluated map expression will return a new map.<br><br>is weird. Yes I know what it means but it is not intuitive. When keys are replaced or not replaced when they are equal is not can seem very strange to those not deep into erlang semantics. <br>
</div></div></blockquote><div><br></div><div>I think the problem here is the description - not the semantics. It's not the keys which are replaced, the crucial</div><div>idea is to have two different syntaxes. This needs a longer explanation to make sense.</div>
<div><br></div><div>Short explanation</div><div>==============</div><div><br></div><div> ':=' means "update an existing key - crash if they key is not present"</div><div> '=>' means "update an existing key OR add a new key" </div>
<div><br></div><div>The value is pretty much irrelevant</div><div><br></div><div>Long explanation of why this is good</div><div>=============================</div><div><br></div><div>We can update an existing map M with the syntax:</div>
<div><br></div><div> M#{ K1 Op V1, K2 Op V2, ... Kn Op Vn}</div><div><br></div><div>Where Op is either => or :=.</div><div><br></div><div>The syntax K => V never generates an error and is used to introduce a new key</div>
<div>or to update an existing key with a new value.</div><div><br></div><div>The syntax K := V is used to update the value of an *existing* key and will</div><div>raise an exception if the key K does not already exist in the map M.</div>
<div><br></div><div>The difference between these two modes of update is crucial, but needs</div><div>a couple of examples to explain:</div><div><br></div><div>Assume we define a map M as follows:</div><div><br></div><div>
M = #{ foo => 1, bar => 2, baz => 3 }</div><div><br></div><div><br></div><div>The update</div><div><br></div><div> M # {foo := 12, bary := 24}</div><div> </div><div>Will fail (raise an exception) since there is no key called bary in the</div>
<div>original map. This is good idea (ROK suggested this in his frames paper)</div><div>since we don't want too accidentally create a new key due to a spelling </div><div>error. This is the crash-early property of the := update syntax.</div>
<div><br></div><div>Crashing later would make debugging difficult, we would accidentally add</div><div>a bad key to a map and learn about it way later.</div><div><br></div><div>The update</div><div><br></div><div> M # {foo := 12, bar := 24}</div>
<div><br></div><div>Will succeed, but more importantly the new map has exactly the same</div><div>keys as the old map (since all the updates are ':=' updates) - and so</div><div>can *share* the same key descriptor. So if we have a very long list of</div>
<div>maps they can be stored in a space efficient manner. (Again this idea</div><div>comes from ROKs frames paper). Björn-Egil's eep didn't mention this</div><div>but the fact that we know that two maps have the same keys from the</div>
<div>syntax make a lot of optimizations possible).</div><div><br></div><div>All of this is possible because there are two operators not one :-)</div></div></blockquote><div><br></div>Exactly and that is very, very useful. Being used to other languages that have maps but don't differentiate between those two use cases, I regularly find myself writing code like:<div><br></div><div>if key in map then do this else do that</div><div><br></div><div>So being able to differentiate between both behaviours by just using the right operator for what I want to do at the time is nice.</div><div><br></div><div><br><blockquote type="cite"><div class="gmail_quote"><div><br></div><div>---</div><div><br></div><div>As regards efficiency, utility, beauty and so on these are subjective.</div>
<div><br></div><div>If you want the last ounce of efficiency records and dicts are not</div><div>going to go away when maps arrive. So if maps have the wrong</div><div>performance characteristics then use the exiting mechanisms.</div>
<div><br></div><div>In the latest addition of my book I've been documenting the changes to maps</div><div>- this chapter has changed three times and has tended to be conservative </div><div>so I haven't (yet) mentioned that keys can be any term (and not just atoms).</div>
<div><br></div><div>I'm rather looking forward to being able to represent things like XML</div><div>and JSON and property lists in a maps and to have an one-size-fits-all</div><div>replacement for dicts and records. I've never really worried about the</div>
<div>last ounce of efficiency - if I want real efficiency I'd change</div><div>language and go to C or program an FPGA.</div></div></blockquote><div><br></div>I'd debate that. As you explain very well in chapter 7 of your book, Erlang is very good at network protocol processing because of its bit syntax. For simple protocols, I'd really want to keep it lightweight and use something efficient like records. Records also allow me to say: this data has a fixed structured format, don't add random keys to it.</div><div><br></div><div>On the other hand, if I'm processing JSON or XML, I'd want the whole power of maps.</div><div><br></div><div>Now if I can have maps behave as efficiently as records for simple structures while giving me a single syntax to deal with both simple and complex structures then I'm all for it.</div><div><br></div><div>Cheers,</div><div><br></div><div>Bruno</div><div><br></div>