<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><br><div><div>On 19 May 2012, at 22:29, Tom Parker wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><span class="Apple-style-span" style="border-collapse: separate; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; font-size: medium; "><span class="Apple-style-span" style="font-family: 'times new roman', 'new york', times, serif; font-size: 16px; ">Therefore, I continue to assert my statement below is correct as written. Records are the issue, and it is the destruction of the name information before it reaches the VM that is the issue.</span></span></blockquote><br></div><div>Actually, I agree with Kostis: the biggest problem is the reliance on</div><div>.hrl files and the preprocessor for sharing code between modules.</div><div><br></div><div>You can put a local function definition in a .hrl file as well, and it</div><div>has been done too. Changes to a record usually trigger badmatch</div><div>or function_clause exceptions if not all modules are recompiled </div><div>and replaced in a coordinated way. This is a problem, for sure,</div><div>but if you make subtle semantic changes to a function in a .hrl</div><div>file, or to a macro (which can expand to pretty much anything),</div><div>then *anything* can happen - including a large set of extremely</div><div>subtle errors that are hard to achieve with records.</div><div><br></div><div>So putting a function definition in a .hrl file can cause some</div><div>really subtle problems. This obviously doesn't mean that functions</div><div>are fundamentally flawed, but yet an example that reliance on</div><div>preprocessors is a dangerous thing. </div><div><br></div><div>The worst thing you can do with records - and it's indeed a bad</div><div>thing - is to rename attributes and use the same positions for </div><div>entirely different data (no, worst would be the *same* data type</div><div>but with a different interpretation). Luckily any half-decent </div><div>programmer will understand enough not to do this.</div><div><br></div><div>Richard O'Keefe has many times stated that a key goal is to</div><div>remove the reliance on the pre-processor.</div><div><br></div><div>If you think about it, Erlang has no facility for sharing structured</div><div>data types between modules, except for code - as Kostis mentioned</div><div>- and pattern matching on the primitive elements of the structure.</div><div><br></div><div>You can provide accessor functions that are exported from the </div><div>same place where the data structure is managed, or you can </div><div>use data structures that are as shallow as to be easy to inspect</div><div>through pattern-matching. If this is not enough, you can pass along</div><div>property lists, which are simple, yet flexible enough to convey just</div><div>about anything - however cannot be quickly inspected with </div><div>pattern-matching. So people trade safety for speed.</div><div><br></div><div>…or rely on convention, which actually works very well.</div><div><br></div><div>Remember that records are little more than syntactic sugar.</div><div>They do not introduce a data type that would offer anything more</div><div>than the above. You could get a similar effect by introducing a </div><div>series of home-cooked macros, expanding to operations and</div><div>patterns on a tuple structure, and then let multiple modules </div><div>rely on them through a .hrl file.</div><div><br></div><div>I even have some old code lying around from the time before </div><div>records. It had a lot of code like this:</div><div><br></div><div>person(name, {person,X,_,_}) -> X;</div><div>person(age, {person,_,X,_}) -> X;</div><div>person(address, {person,_,_,X}) -> X.</div><div><br></div><div>person(name, X, {person,A,B,C}) -> {person,X,B,C};</div><div>person(age, X, {person,A,B,C}) -> {person,A,X,C};</div><div>person(addr, X, {person,A,B,C}) -> {person,A,B,X}.</div><div><br></div><div>A bit fiddly to create, but easy to verify through visual inspection.</div><div>Of course, you could put that in a .hrl file and use as a 'shrared</div><div>data type'. It would suffer from roughly the same problems as </div><div>records.</div><div><br></div><div>The obvious limitations with records were the subject of animated</div><div>discussion even before they were added to the language. You</div><div>wouldn't recall this unless you were a member of a pretty small </div><div>group of people debating this on a mailing list inside Ericsson, long</div><div>before the Open Source release.</div><div><br></div><div>Even then it was agreed that the proper way to do it was to introduce</div><div>a new data type. As my memory serves, the problem with that was </div><div>that JAM didn't have any more type tags to use. A redesign of the </div><div>memory management structure in the VM would be required in order</div><div>to add new data types. In light of this, records were seen as a</div><div>cost-efficient way to solve a common problem of copy-paste </div><div>programming.</div><div><br></div><div>Later on, I believe it was the HiPE team that proposed a new tagging</div><div>scheme and wrote some working code to demonstrate. By the time</div><div>it was integrated into Erlang, records had become ubiquitous, and </div><div>could not be easily replaced.</div><div><br></div><div>If my recollection is faulty, the old-timers can correct me. I recall this</div><div>playing out right after I joined Ericsson in 1996.</div><div><br></div><div>(The new tagging scheme was introduced in R7B in 2000, and is described</div><div>in Mikael Petterson's PhD thesis: <a href="http://www.it.uu.se/research/publications/reports/2000-029/">http://www.it.uu.se/research/publications/reports/2000-029/</a>)</div><div><br></div><div>One can argue that it's taken a long time to correct this issue, and </div><div>add a structured data type with all the goodness of records and </div><div>none of their drawbacks. The reasons:</div><div><br></div><div>- Erlang, even taking this into account, is a darn good language for</div><div> writing complex, robust and scalable systems.</div><div>- Convention actually works pretty well in practice.</div><div>- The OTP team wanted to get it right the second time.</div><div>- Backwards compatibility is considered extremely important in the</div><div> Erlang world (exactly because we don't want to break the </div><div> complex, robust and scalable systems already written in Erlang)</div><div><br></div><div>BR,</div><div>Ulf W</div><div><br></div><div apple-content-edited="true">
<div><div>Ulf Wiger, Co-founder & Developer Advocate, Feuerlabs Inc.</div><div><a href="http://feuerlabs.com">http://feuerlabs.com</a></div></div><div><br></div><br class="Apple-interchange-newline">
</div>
<br></body></html>