Inside the Elixir official documentation, the guards sections states:
Not all expressions are allowed in guard clauses, but only a handful of them. This is a deliberate choice. This way, Elixir (and Erlang) can make sure that nothing bad happens while executing guards and no mutations happen anywhere. It also allows the compiler to optimize the code related to guards efficiently.
What does ‘bad’ mean here? Is it only referring to mutations and non-optimizable code?
Patterns and Guards are a small separate language inside Elixir (and Erlang). Compiler takes a look at the guards and patterns and generates very efficient BEAM assembly. Therefore, guards are limited only to a set of declarative functions which you can find here (for erlang) and here (for elixir)
For example,
case something do
1 -> ...
2 -> ...
3 -> ...
a when is_atom(a) -> ...
b when is_binary(b) -> ...
end
Will generate a jump table, and switching in this kind of case will always be O(1)