Erlang Notes

erlang q&a
Login

erlang q&a

  1. How do I use rebar3 format outside of a rebar3 project?
  2. This hex.pm project's source is a broken link. Can I still use it?
  3. Why doesn't elvis like records in type specs?

How do I use rebar3 format outside of a rebar3 project?

You pick up Erlang. You want all your usual tools with it. One of those tools is auto-formatting. Does Erlang have an auto-formatter? It does! Can you use it? ... With some effort, you can. But, seemingly, you can't use it as like a normal auto-formatter. These tools document industrial use but not one-off use!

You can use it as you expected, though, if you add it as a rebar3-wide plugin:

$ cat ~/.config/rebar3/rebar.config
{plugins, [
  {rebar3_format, "1.3.0"}
]}.
{format, [{formatter, default_formatter}, {options, #{inline_clause_bodies => true}}]}.

With that configuration in place, the following just works:

$ cat h1.erl
-module(h1).

-export([hello/0, hello/1]).

hello() ->
    hello("world").

hello(Name) ->
    io:fwrite("Hello, ~s!~n", [Name]).
$ rebar3 format --files=h1.erl
$ cat h1.erl
-module(h1).

-export([hello/0, hello/1]).

hello() -> hello("world").

hello(Name) -> io:fwrite("Hello, ~s!~n", [Name]).

Or delete the last line of that rebar3.config to get the first h1.erl as the formatted result.

An alternative is erlfmt:

{plugins, [
  {erlfmt, "1.3.0"}
]}.
{erlfmt, [write]}.

With this rebar3.config in place, this works:

$ cat h1.erl
-module(h1).
-export([hello/0, hello/1]).

hello() -> hello("world").

hello(Name) -> io:fwrite("Hello, ~s!~n", [Name]).

what_is(Erlang) -> case Erlang of movie -> [hello(mike, joe, robert), credits]; language -> formatting_arguments end.
$ rebar3 fmt h1.erl
$ cat h1.erl
-module(h1).
-export([hello/0, hello/1]).

hello() -> hello("world").

hello(Name) -> io:fwrite("Hello, ~s!~n", [Name]).

what_is(Erlang) ->
    case Erlang of
        movie -> [hello(mike, joe, robert), credits];
        language -> formatting_arguments
    end.

This hex.pm project's source is a broken link. Can I still use it?

You can, because hex.pm is a separate host of the projects published on it. You can also explore them, f.e. https://preview.hex.pm/preview/fossil/0.1.0 has a file selector at the top that includes all of fossil 0.1.0's assets.

Why doesn't elvis like records in type specs?

I get this complaint from elvis:

    - The spec in line 20 uses a record, please define a type for the record and use that instead.

about this code:

-record(session, {
    active :: 1..5,
    stacks :: {list(#vocab{}), list(#vocab{}), list(#vocab{}), list(#vocab{}), list(#vocab{})}

-spec save(#session{}) -> 'ok'.  % line 20

What's elvis's problem, hah? Typespecs support records. Dialyzer works with this. Why shouldn't I use it?

https://youtu.be/yAkvVHnAKNI?t=733 goes into a reason why, and seems to amount to dialyzer treating record types as invariants, enforced within functions, whereas other type specs are enforced only at function boundaries.