PragTob

PragTob

Blog Post: 10 Elixir gotchas

Elixir is a great language, but some behavior can be unintuitive, confusing and in the worst case lead to bugs. So, I took a look at 10 Elixir gotchas explaining why they exist and how to avoid them!

Most Liked

sasajuric

sasajuric

Author of Elixir In Action

Another gotcha with module attributes is that each reference injects the value, which can increase disk & mem usage. For example:

defmodule Foo do
  @x Enum.to_list(1..1_000_000)

  def foo, do: @x
  def bar, do: @x
end

Here we inject two identical large lists in the code, and the resulting file is 6 MB.

In contrast, the following code:

defmodule Foo do
  def foo, do: x()
  def bar, do: x()

  defp x, do: unquote(Enum.to_list(1..1_000_000))
end

produces a 4 MB beam, because the list is injected into the compiled beam only once.

In addition, I consider the 2nd version more flexible, because the “constant” can be provided after the implementation, which I often find better than listing various constants at the top of the file.

It’s also worth mentioning that both versions produce constants, as in terms which are handled in a special way by the runtime. See here for details.

BartOtten

BartOtten

Great post.

One more: is_atom(nil) == true as nil is an atom. However, most people mean a defined atom and not ‘undefined’ nil.

dwark

dwark

I got caught off guard by:

 [1, 2, 3] -- [1, 2, 3] -- [1, 2, 3]
[1, 2, 3]

After checking, the docs spell it out neatly once I starting looking for an explanation
(-- is right-associative).

BartOtten

BartOtten

Got a new gotcha today

Elixir’s ++/2 operator (list concatenation) has a special clause: If the right-hand side is not a list, the operation returns that right-hand side value instead of raising an error.

Never knew about it. Did bite me. Type checker did not warn that the enumeration would possibly
raise an exception. :frowning:

iex(1)> [] ++ nil
nil
iex(2)> [] ++ :foo
:foo
iex(3)> [] ++ "bla"
"bla"

The source in erlang is clear. This is the comment on the nil as right-hand side:

if (is_nil(lhs)) {
        /* This is buggy but expected, `[] ++ 'not_a_list'` has always resulted
         * in 'not_a_list'. */
        return rhs;

Doubt I like the behavior, but alas…there it is.

josevalim

josevalim

Creator of Elixir

The term ordering is essential for data structures such as maps, sets, ordsets, orddict, and others. Dynamic languages have heterogeneous collections, which means you can have keys, lists, and sets with distinct data types. Some of these data structures are more efficiently implemented by having a total order. If Erlang/Elixir only allowed you to compare the same data types, those data structures would have to define their “total” ordering, and it would ultimately be inefficient, especially for composite data types (e.g. storing structs inside sets, such as a set of dates).

The main source of confusion is because Elixir comparison operators are structural, not semantic. But there are good reasons for those as well. The docs go in detail over this: Kernel — Elixir v1.17.0-dev

The mutability of module attributes shouldn’t be a concern, really. Defining modules in Elixir is mutable a whole. defmodule, def, attrs are all mutable operations that define a module, functions, etc as you execute them. This what allows you, for example, to programmatically define a function. But, as meta-programming, those abilities are only really there at compile-time by design.

Where Next?

Popular in Blog Posts Top

pillaiindu
Our very handsome and humble José Valim (@josevalim) just published Kubernetes and the Erlang VM: orchestration on the large and the sma...
New
New
brainlid
Livebook was created for machine learning in Elixir but Livebook isn’t limited to machine learning. I found it works really well for docu...
New
axelson
I talk about how I really like to use runtime configuration and discuss some common pitfalls of configuration in Elixir.
New
paulanthonywilson
Whatever your Nerves project does, there’s a good chance that it can be enhanced by securely connecting to a Phoenix Server in the cloud;...
New
bram209
Hello everyone, I just published my first blog post ever. I am learning Elixir, OTP & Phoenix and wanted to start a blog for a while ...
New
AstonJ
I think <span class="hashtag-icon-placeholder"></span>liveview is going to be a big topic in the foreseeable future, so wondering whether...
New
Paradox
Testing is an important part of any modern piece of software. But writing tests can quickly become an exercise in frustration, with tons ...
New
gaggle
This post explores different ways to do test automation in Elixir, focusing on how to handle dependency injection — covering patterns, li...
New
ragamuf
Does the world need another How to create a blog article? Maybe not. But then again, creating something out of nothing is what we love....
New

Other popular topics Top

Qqwy
Update: How to use the Blogs &amp; Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3268 119930 1237
New
JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 45766 226
New
grych
Hi folks, Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
639 49522 488
New
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
beno
I will often find my self writing things similar to: case some_value do nil -&gt; something() "" -&gt; something() _ -&gt; someth...
New
lucidguppy
I have a super simple question about elixir - how would I take a file like this foo bar baz and output a new file that enumerates th...
New

We're in Beta

About us Mission Statement