Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Idiomatic Erlang

Jade Allen
November 13, 2017

Idiomatic Erlang

Some guidelines to consider when you're doing greenfield Erlang development.

Jade Allen

November 13, 2017
Tweet

More Decks by Jade Allen

Other Decks in Technology

Transcript

  1. Style suggestions u Use inline type specifications and documentation tools

    u Use list comprehensions u Use explicit functions in higher order functions u Don’t nest case statements u Use sweet syntactic sugar for maps and record pattern matching u Reply to unknown gen_server call messages with a weird answer. (Why?) u Use erlang:error/2 instead of error/1 u Start new projects using rebar3 templates u Make your editor help you (find and use Erlang plugins for your code editor) u Finite state machines are powerful – exploit their power
  2. Example code -spec repeat( FunName :: atom() | function(), Args

    :: [ term() ], Count :: pos_integer() ) -> Result :: term() | { error, Reason :: term() }. %% @doc This function repeats calls to a function name which may fail %% given by the FunName parameter for Count number of times. repeat(_FunName, _Args, 0) -> {error, count_reached_zero); repeat(FunName, Args, Count) when is_atom(FunName) -> do_repeat({?MODULE, FunName}, Args, Count); repeat(FunName, Args, Count) when is_function(FunName) -> do_repeat(FunName, Args, Count); repeat(Other, _Args, _Count) -> erlang:error({error, badarg}, [Other, Args]). do_repeat(Fun, Args, C) -> try erlang:apply(Fun, Args) catch _:_ -> repeat(FunName, Args, C – 1) end.
  3. Type specifications u Dialyzer is a type analysis tool for

    Erlang/Elixir. u You give dialyzer hints by providing a type specification for your (public) functions. u They help remind you what the arguments to a function are and what sorts of output might be returned. u Dialyzer can help you spot instances in your code when the specification is not true.
  4. List comprehensions u Powerful and compact way to filter and

    iterate over a collection of items in a list. u Can replace lists:map and lists:filtermap [[ prepare_valid_element(E) || E <- List, E /= undefined ]]. lists:filtermap( fun(E) when E /= undefined -> {true, prepare_valid_element(E)}; (_E) -> false end, List).
  5. Explicit function names u Using explicit function names gives two

    benefits: u Much better stack traces u Easy to write unit tests for the whole function and the higher order function lists:map(fun(X) -> X*X end, lists:seq(1,5)). lists:map(fun double/1, lists:seq(1,5)). double(X) -> X*X.
  6. Don’t nest case statements u They’re hard to read and

    hard to reason about. u Use guard clauses and explicit functions. case foo(Arg1, Arg2) of true -> case of bar(Arg2) of true -> min(1, Arg1); false -> 100 end; false -> {{error, badarg}, Arg1} end.
  7. Don’t nest case statements u They’re hard to read and

    hard to reason about. u Use guard clauses and explicit functions. case foo(Arg1, Arg2) of true -> case of bar(Arg2) of true -> min(1, Arg1); false -> 100 end; false -> {{error, badarg}, Arg1} end.
  8. Don’t nest case statements case foo(Arg1, Arg2) of true ->

    test_arg2(Arg1, Arg2) false -> {{error, badarg}, Arg1} end. test_arg2(Arg1, Arg2) -> case bar(Arg2) of true -> min(1, Arg1); false -> 100 end.
  9. Sweet syntactic sugar handle_call({incr, _Arg}, _From, S = #state{ state

    = lock }) -> {reply, {error, locked}, S}; handle_call({incr, Arg}, _From, S = #state{ cnt = C }) -> {reply, ok, S#state{ cnt = C + Arg }}. incr_foo(V, Map = #{ foo := Current }) -> Map#{ foo := Current + V }.
  10. Use weird reply to unknown message handle_call(Call, From, State) ->

    ?LOG("Unknown call ~p from ~p!!”, [Call, From]), {reply, unknown_call_message_die_die_die, State}.
  11. Use erlang:error/2 u Provides the specific bad argument along with

    the error atom in a stack trace. This is really helpful! u Demo
  12. Remainder u Use rebar3 templates to start new projects u

    Make your editor help you! u Don’t ignore finite state machines! They provide great clarity/insight into your programming intentions.