DEV Community

Brujo Benavides
Brujo Benavides

Posted on

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…

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.
Enter fullscreen mode Exit fullscreen mode

You can compile it and execute its function…

    1> c(my_mod).
    {ok,my_mod}
    2> my_mod:whoami().
    my_mod
    3>
Enter fullscreen mode Exit fullscreen mode

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

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

    -spec whoami() -> atom().
    whoami() -> ?MODULE.
Enter fullscreen mode Exit fullscreen mode

As expected, same results…

    1> c(my_mod).
    {ok,my_mod}
    2> my_mod:whoami().
    my_mod
    3>
Enter fullscreen mode Exit fullscreen mode

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).
Enter fullscreen mode Exit fullscreen mode

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.
Enter fullscreen mode Exit fullscreen mode

It actually works!! Look at that…

    1> c(my_mod).
    {ok,my_mod}
    2> my_mod:whoami().
    my_mod
    3>
Enter fullscreen mode Exit fullscreen mode

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.
Enter fullscreen mode Exit fullscreen mode

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

    1> c(my_mod).
    my_mod.erl:5: 
    my_mod.erl:2: function whoami/0 undefined
    my_mod.erl:4: spec for undefined function whoami/0
    error
Enter fullscreen mode Exit fullscreen mode

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)


This article was first published in Erlang Battleground as Unbalanced Parentheses.

Top comments (0)