<div dir="ltr">So I finally did it the old ways using records and accessor functions over it. To answer to joe and other, the main goal was to have more clarity and consistency over the time in the way you will access the data. Right now the data structure is pretty clear  and can only be augmented if I have to introduce new properties. So I guess it will be OK.<div><span style="line-height:1.5"><br></span></div><div><span style="line-height:1.5">(this thread was very </span>interesting<span style="line-height:1.5"> to learn how others uses the records, we should have more topics like this :) which let me remember </span><a href="http://www.erlangpatterns.org/">http://www.erlangpatterns.org/</a> ..., I wonder how the project works as of today)<br></div><div><br></div><div>- benoit</div></div><br><div class="gmail_quote"><div dir="ltr">On Tue, Mar 1, 2016 at 4:15 AM Siraaj Khandkar <<a href="mailto:siraaj@khandkar.net">siraaj@khandkar.net</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On 2/29/16 3:02 PM, Torben Hoffmann wrote:<br>
><br>
><br>
> Jesper Louis Andersen <<a href="mailto:jesper.louis.andersen@gmail.com" target="_blank">jesper.louis.andersen@gmail.com</a>> writes:<br>
><br>
>> [ text/plain ]<br>
>> On Mon, Feb 29, 2016 at 4:28 PM, Siraaj Khandkar <<a href="mailto:siraaj@khandkar.net" target="_blank">siraaj@khandkar.net</a>><br>
>> wrote:<br>
>><br>
>>> In other words, I'm saying it is very possible to have this cake (of<br>
>>> public structure) and eat it too (in private, without anyone accessing the<br>
>>> rapidly-changing, secret cream) :)<br>
>><br>
>><br>
>> You are so close to the idea of view types, and Torben hinted me I should<br>
>> say something about them :)<br>
>><br>
>> One advantage of a function is that it doesn't have to give you the field<br>
>> outright, but can provide ways to dynamically cast that structure into<br>
>> another structure you export. Two really good examples is that you can<br>
>> return some kind of tuple depending on the contents of the data and thus<br>
>> you can build a case match on the data. This ad-hoc<br>
>> for-the-purpose-construction of a datatype can often yield far more precise<br>
>> code since it splits analysis of what is *in* the datastructure from<br>
>> computation which says what to *do* about that data. Say we have a #uri{}<br>
>> record. The path component has many possible representations: a binary(), a<br>
>> list of binaries, an iterator, and so on. Different view-functions would<br>
>> give you different ways to handle that binary.<br>
>><br>
>> Another nice thing is that functions can give you are<br>
>> zipper/derivative/delimiting-continuation over the data in the structure.<br>
>> The path-component can then be unfolded one path-entry at a time:<br>
>><br>
>> pth(X) -><br>
>>      case http_uri:unfold_path(X) of<br>
>>          none -> ...;<br>
>>          {some, C, X2} -><br>
>>             ... C ... pth(X2)<br>
>>      end.<br>
>><br>
>> or you can imagine a gb_trees/gb_sets like iterator over the data structure.<br>
>><br>
>> A plain map() cannot give any of these ideas, and its transparency also<br>
>> tightly couples your code to the map() structure. So one has to carefully<br>
>> weigh what kind of interface you want in the long run. I much prefer views<br>
>> of the data structures if possible since it allows for more freedom in the<br>
>> long run, but it requires you to be able to figure out what kind of<br>
>> functions you would need a priori on the data. On the other hand, it<br>
>> provides for much better hiding of what is going on inside the module,<br>
>> which allows you more flexibility regarding backwards compatibility.<br>
>><br>
>> In other words: exporting records across application boundaries tend to<br>
>> lock them down, so be pretty sure they are set in stone. Also think hard if<br>
>> you want every user to implement the analysis code. The view is much like<br>
>> in a database: do you export the raw records, or do you expose a<br>
>> transactional API through stored procedures which tell you what you can do<br>
>> with the data?<br>
>><br>
>><br>
> Why attempt to write a half-baked answer when you can ask Jesper to<br>
> explain it well?!?! [1]<br>
><br>
> Look at Cowboy and Webmachine for examples of how to provide functions<br>
> to work with a request.<br>
><br>
> Both have a very rich API for extracting relevant things out of the<br>
> request record.<br>
> No need to start poking into that record on your own.<br>
><br>
<br>
I think you missed the point, see my reply to Jesper :)<br>
<br>
That said, since you bring-up Cowboy, it is a good example of what I<br>
mean by other constraints and plans - an author might want to fill-in<br>
some of the fields lazily (such body in cowboy_req), in which case<br>
per-field accessor functions are their only good choice, unless, of<br>
course, they want to consider compound subsets (of, say, only the<br>
eagerly calculated parts, but I digress - it isn't the important<br>
point)... :) Anyhow, without a specific application and vision for it's<br>
future, which API design direction to take is not something you or I can<br>
finalize here - it depends on a bunch of things.<br>
<br>
The important point is that, by using an abstract type, you're not at<br>
all limiting yourself to exposing per-field accessor functions - you can<br>
do other things (if you wish), as long as you make a clear distinction<br>
between internals and API.<br>
_______________________________________________<br>
erlang-questions mailing list<br>
<a href="mailto:erlang-questions@erlang.org" target="_blank">erlang-questions@erlang.org</a><br>
<a href="http://erlang.org/mailman/listinfo/erlang-questions" rel="noreferrer" target="_blank">http://erlang.org/mailman/listinfo/erlang-questions</a><br>
</blockquote></div>