[erlang-questions] macro definition map for both assignment and matching

Frans Schneider schneider@REDACTED
Fri Sep 26 08:36:30 CEST 2014


Dear Fred,

Thanks for the advice. Rethinking the attributes issue, I came to the 
conclusion that matching is overkill. One of the problems I have to deal 
with is that I don't have access to the protocol specs and have to do a 
lot of reverse engineering and use trial and error.

About solution number 3, using records, and not sharing record 
definitions across modules. Is that because the compiled code gets out 
of sync? I found records to be very nice in partial matching and use 
them for that reason. The syntax is ok for me and with the macros, the 
complexity of nested records can be hidden.

By the way, I don't use the state as one might conclude from the example 
I gave. Should have been more precise on that point.

Frans

On 09/25/2014 06:42 PM, Fred Hebert wrote:
> On 09/25, Frans Schneider wrote:
>> Hi list,
>>
>> I am using maps to represent attributes of an entity and use macro's to
>> simplify the code.
>> As an example:
>>
>> [...]
>>
>> This is great for creating the maps, but now I also want to use the macro's
>> for pattern matching which requires the => to become :=. as in
>>
>> handle_call(?MEDIA_URL_ATTRS(Media_type, Url, Name, Size), ....) ->
>>      ...
>>
>> Of course, I could just copy / paste / global replace / rename the macro's
>> to a another set of macro's, but that seems rather silly. There are
>> approximately 200 macro's, many of them nested, which makes maintaining the
>> code an issue.
>>
>> Any suggestions on making this work?
>>
>> Frans
>>
>> PS
>> I started out using lists for the attributes, but matching only works if the
>> order of the attributes can be guaranteed, which is not the case. Also,
>> partial matching works rather nice with maps.
> Here's a pretty cool set of options if what you need is something of the
> form LABEL(Pos1, Pos2, Pos3, Pos4).
>
> 1. Use tuples: {media_url_attrs, MediaType, URL, Name, Size}
>
> Nice aspects:
> - forces you to define them properly in messages, rather than any kind
>    of random map that someone can pass your server. Explicit protocols
>    are the best protocols
> - Lowest memory overhead possible for this while remaining readable
> - Can be used both for pattern matching and assignment, although it
>    requires an explicit set of all values (setelement is otherwise
>    possible to use!)
>
> Downsides:
> - Not practical for frequent updates to only a subset of elements
> - Cannot pattern match on a subset of the elements
>
> 2. Use a list in a tagged tuple: {media_url_attrs, [MediaType, URL, Name, Size]}
>
> Nice aspects:
> - Allows matching on variable element numbers
>
> Downsides:
> - Lists tend to have no 'ordered' meaning semantically, proplists help
>    with that but you didn't like them
>
> 3. Records
>
> Nice aspects:
> - Meant for static number of elements
> - As efficient as tuples, but allow partial matching and assignment
>
> Downsides:
> - they require shared definitions across modules (don't do that)
> - Cumbersome syntax
> - No access to variable keys (that's on purpose)
>
> 4. Maps
>
> Nice aspects:
> - Made for variable number of elements (like dict, etc.)
> - Can be used more like lists, without the proplists interface to be
>    used
>
> Downsides:
> - No variable variable names (yet)
>
> 5. Functions: media_url_attributes(Key, Term) -> Val
>
> Nice aspects:
> - Internal representation can remain hidden
>
> Downsides:
> - Doesn't allow pattern matching
>
> 6. Macros:
>
> Nice aspects:
> - Same advantages as function
>
> Downsides:
> - Same downsides as tuples
> - Also why would you do that when everything else mentioned here may
>    work?
>
>
> In conclusion:
>
> - You're handling messages. Please define your protocols explicitly and
>    stick that stuff in a tuple
> - You're moving things inside your state. Please consider using a record
>    for your state, it's what they were meant for
> - The format of a message being passed and a piece of state you keep
>    around do not need to be the same, and picking the right data
>    structures will likely help you get nicer programs rather than shoving
>    it all in a map.
> - I am unfortunately not surprised you're having maintenance issues with
>    ~200 such macros (you're getting all the advantages of function calls
>    with all the downsides of records). Why do you even need them in the
>    first place? If all you need are default values, please consider using
>    records, or using a default map that you merge with a user-submitted
>    map.
>
> Regards,
> Fred.




More information about the erlang-questions mailing list