Today’s Erlang Thursday takes a look at the erl_tidy
module in Erlang, and we start with erl_tidy/1.
erl_tidy:file/1
takes a filename, and “tidies” up and pretty prints the sourcecode in the file specified.
As I have a quick FizzBuzz solution hanging around in a tmp directory, I will just start with that file, and see what erl_tidy:file/1
does to that file, as I am pretty sure it is not completely pretty.
-module(fizzbuzz). -export([fizzbuzz/1]). fizzbuzz(N) -> Translations = lists:map(fun translate/1, lists:seq(1, N)), lists:foreach(fun(Item) -> io:format("~s~n", [Item]) end, Translations). translate(N) when N rem 3 =:= 0 andalso N rem 5 =:= 0 -> 'FizzBuzz'; translate(N) when N rem 3 =:= 0 -> 'Fizz'; translate(N) when N rem 5 =:= 0 -> 'Buzz'; translate(N) -> integer_to_list(N).
We open up a new Erlang shell and call erl_tidy:file/1
with the fizzbuzz.erl.
erl_tidy:file("fizzbuzz.erl"). % fizzbuzz.erl:6: replacing call to `lists:map/2' with a list comprehension. % fizzbuzz.erl:6: changing application of implicit fun to direct local call. % ok
Looks like it didn’t like the way I was using map in the original file, and it changed the way I was calling translate/1
.
Let’s close out the shell, and see what the directory looks like now.
ls -l total 16 -rw-r--r-- 1 proctor staff 402 Sep 9 22:06 fizzbuzz.erl -rw-r--r-- 1 proctor staff 405 Sep 9 22:05 fizzbuzz.erl.bak
Let’s take a look at fizzbuzz.erl.bak
and see what is in that file, mainly to confirm that it is the content that was originally in fizzbuzz.erl
.
-module(fizzbuzz). -export([fizzbuzz/1]). fizzbuzz(N) -> Translations = lists:map(fun translate/1, lists:seq(1, N)), lists:foreach(fun(Item) -> io:format("~s~n", [Item]) end, Translations). translate(N) when N rem 3 =:= 0 andalso N rem 5 =:= 0 -> 'FizzBuzz'; translate(N) when N rem 3 =:= 0 -> 'Fizz'; translate(N) when N rem 5 =:= 0 -> 'Buzz'; translate(N) -> integer_to_list(N).
That does indeed look like the original contents of fizzbuzz.erl
.
Now let’s take a look at the updated fizzbuzz.erl
file to see what the result of erl_tidy:file/1
is.
-module(fizzbuzz). -export([fizzbuzz/1]). fizzbuzz(N) -> Translations = [translate(V1) || V1 <- lists:seq(1, N)], lists:foreach(fun (Item) -> io:format("~s~n", [Item]) end, Translations). translate(N) when N rem 3 =:= 0 andalso N rem 5 =:= 0 -> 'FizzBuzz'; translate(N) when N rem 3 =:= 0 -> 'Fizz'; translate(N) when N rem 5 =:= 0 -> 'Buzz'; translate(N) -> integer_to_list(N).
As the message said, we have a list comprehension instead of map
, and it is calling the translate/1
function directly, as mentioned in the two output messages.
It also put the end
of the fun
passed to lists:foreach/2
on a new line, and the list Translations
on a new line as well.
And finally, the last three function clauses of translate/1
were combined into single line functions, and the trailing newline at the end of the file was removed.
According to the documentation page, had the fizzbuzz.eerl
file had any unused functions, those would have also have been tidied up, along with “updating obsolete constructs and function calls, etc.”
All in all, a nice little tool of an Erlang application that can help your code keep a certain style and cleanliness to it.
–Proctor
Stay in touch… one day it will be added to gadget (https://github.com/inaka/gadget/issues/31) and you’ll be able to automatically (and configurably) run it on all your code !!