[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