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
:: [ 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.
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.
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).
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.
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.
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.