Unbalanced Parentheses

…or another reason not to use macros

This is an article about something I showed live at the Erlang & Elixir Factory San Francisco 2017. It’s about what you can and can not do if you are fancy with your module attributes in Erlang.

Golden Gate Park, from GrandView Park, SF

Notes

First of all, Federico: sorry for stealing your name. It was just too cool not to ;)

That said, here is the video of the whole talk, in case you want to watch it…

Erlang Oddities at EEF SFBay 2017 — Thanks Erlang Solutions

And if you prefer Spanish…

Ok, enough with the links! Let’s get down to business…


The Usual Suspects

This is a perfectly valid Erlang module:

-module(my_mod).
-export([whoami/0]).
-spec whoami() -> atom().
whoami() -> my_mod.

You can compile it and execute its function…

1> c(my_mod).
{ok,my_mod}
2> my_mod:whoami().
my_mod
3>

This is also a perfectly valid Erlang module (now using a macro):

-module(my_mod).
-export([whoami/0]).
-spec whoami() -> atom().
whoami() -> ?MODULE.

As expected, same results…

1> c(my_mod).
{ok,my_mod}
2> my_mod:whoami().
my_mod
3>

The Cool Guy

But… that spec attribute there has no parentheses around it. Can we also remove the parentheses around the other attributes? The docs are not very clear about that. They show the following general syntax for attributes:

-Tag(Value).

But then there are attributes like spec, type or callback that are shown without parentheses. So, why not give it a try? How much nicer would that export be without the parentheses around the brackets, right?

-module my_mod.
-export [whoami/0].
-spec whoami() -> atom().
whoami() -> my_mod.

It actually works!! Look at that…

1> c(my_mod).
{ok,my_mod}
2> my_mod:whoami().
my_mod
3>
YEY!! (from Primo GIF)

I’m not writing a parentheses there anymore!


Not so Fast, Cowboy!

Well… I’m not a fan of macros, but sometimes I end up using the predefined ones, like I did with ?MODULE above

-module my_mod.
-export [whoami/0].
-spec whoami() -> atom().
whoami() -> ?MODULE.

Now if you try to compile that module, you’ll find quite an unexpected result…

1> c(my_mod).
my_mod.erl:5: undefined macro 'MODULE'
my_mod.erl:2: function whoami/0 undefined
my_mod.erl:4: spec for undefined function whoami/0
error
WAT (from Primo GIF)

What’s going on here?

This time I literally have no clue. I can see that, in order to use the macro ?MODULE you have to use parentheses around your module name. But I haven’t done any research to find the root cause of it. That’s mostly because I have a very distinctive feeling that it will take me to the land of parsers, compilers, etc. and that’s a place I like to stay away from.

So, for this article, dear reader, if you are brave enough to go deep into the realm of the Erlang compiler and its friends and find out what’s going on, please let me know in the comments below.

And of course, if you can go ahead and fix this by sending a Pull Request to erlang/otp

Office Space (1999)
Show your support

Clapping shows how much you appreciated Brujo Benavides’s story.