[erlang-questions] macro definition map for both assignment and matching
Fred Hebert
mononcqc@REDACTED
Thu Sep 25 18:42:43 CEST 2014
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