PragTob

PragTob

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!

19 474 11

Most Liked

Eiji

Eiji

On Elixir forum there are few topics about those and other gotchas already:

Regarding your list:

  1. Elixir developers by default are diabetics. syntax sugar or pretty printing is a common thing. Over time you would find it rather handy than confusing. You just need to get used to sugar. When you learn a language you should not compare it to others. If doing so I as an Elixir developer would say that mutable variables are confusing. Are they really? In many cases especially sharing mutable data between processes leads to terrible things that are often hard to track well. However some gotchas are actually gotchas only for people who didn’t spend their time to read a syntax reference and other official guides. Simply you are going to be surprised expecting English characters in Chinese language.

  2. charlist is not just an old concept, but a way to handle same thing with other data type.

iex> list = ~c"a"
iex> <<List.first(list)>>
"a"

Because of different type processing and updating data is entirely different, so in some cases you can use one or another to speed up your code. For those reasons we have something in between which is called iolist:

  1. At start it’s confusing, but only a bit. Soon people ask themselves how they could live without that. I can’t imagine that I would pattern-match dozens of keys including all possible cases where some keys may not exist - all of that just to pattern-match on one or few keys.

  2. I don’t remember if I ever did a pattern-match on range, so that example surprised me for a 1ms. Anyway I prefer strict things and I’m always using a struct module when doing pattern-matching on structs. Therefore it was never confusing for me at all.

  3. That’s a good point. It was a good decision at first, but then people started to work on polymorphic data and the concept has been messed up. Without that rarely calling stuff like Map.get/2 would not be a pain at all.

  4. Who said that keywords are the only way for options? As same as charlist vs string topic. Sometimes we use keyword lists and sometimes we use maps. Again expecting lists to behave like maps is weird and shows that someone did not understand why the keyword lists are used for.

  5. That’s only problem if you do not write much guards. It’s funny to see a fully documented function which does not checks if integer parameter is actually an Integer. No matter if we talk about function guards or a type system if they would not be used then the bugs would not be discovered. While I’m aware what bugs could happen I never had such a case personally. I don’t write much guards and documentation only in small pet projects that I’m working on locally.

  6. Not sure how about you, but I know about comparison operators only from used them on integers and floats. Maybe in some languages they are more widely used for other types as well, but I think that I never assumed that such operators would work on date/time structs. I know I’m weird, my first Linux distribution was Gentoo, so maybe I like to go the hard way and I don’t have problem with that. For me it’s rather more like I don’t assume that some behaviour is implemented before I would not read it from documentation. One time I did that with module attributes as I expected them to be equivalent ones for Ruby’s attributes. Once I “learned” to read documentation properly I started to have less problems.

  7. For me this is the biggest gotcha from your list. The most surprising is not this itself, but in context with a . (dot) operator, as it raises KeyError when you try to fetch same thing with this operator, see:

iex> nil.something
** (KeyError) key :something not found in: nil

If you are using the dot syntax, such as map.field, make sure the left-hand side of the dot is a map
    iex:1: (file)
iex> nil[:something]
nil
  1. Module attributes are of course important part of Elixir, but you would see their value much more when you would learn meta-programming. When do so you would never expect a warning on “redefining” a module attribute. :smiley:

Summary

Gotchas for most people are things that do not work they way they want. In many cases reading documentation would not cause confusion. After some practice they can’t be called weird, but just different from concepts in other languages. That’s not bad thing. I would even say that’s expected to happen. If every language would work the same way as others we would use just one language. :joy:

Don’t assume something before you understand it and it’s context. Simply by following this rule you shouldn’t have bigger problems with most languages especially the modern, high-level ones. :+1:

PragTob

PragTob

Thanks for the links, I must say I didn’t review a lot before but went off what I’ve seen people learning Elixir struggle with in real life.

I get your point about “if you read the docs, it shouldn’t be surprising and you shouldn’t expect it to work in any way”. That’s not how most people work though (imo), they’ve learned something in another programming language and it’s difficult to completely switch that part of esp. when learning. Particularly there are some things where I’d say elixir & erlang behaves extra weird.

Yup I know, but I do think bringing up that goes beyond the scope of the blog post

Never suggested that. I think how maps are matched is great and of course there should be no other way. It makes sense when you think about how their matching works, but still people sometimes expect %{} to match the empty map.

It’s not the only way, but it’s the default way that most Elixir functions use. The preference is also discussed in the discussion I linked Passing in options: Maps vs. Keyword lists - Chat / Discussions - Elixir Programming Language Forum The point isn’t about expecting them to work like maps, but that they are the default (in Elixir, Erlang switched over) and are less handy (imo) to handle this use case.

The problem here is that it “works” it just does something unexpected which isn’t exactly a great DevX. Also lots of Elixir programmers are coming from Ruby (like myself) and there this works - I don’t know about other languages but I’ve seen folks from different programming backgrounds be stung by this.

Why is that surprising? To me this isn’t surprising at all as that’s how . works - it raises if the key isn’t there and the key isn’t there.

I don’t expect a warning there - it’s just unexpected that our workaround for constants can actually change its value during the course of a module which isn’t really… constant. I know why it is and how it’s used, doesn’t make that property less confusing for new comers or potentially dangerous for a “constant” use case especially in huge modules (which you shouldn’t have, but many people do) easily producing odd bugs.

jaeyson

jaeyson

Spot on!

Where Next?

Popular Backend topics Top

paulanthonywilson
Post on using UDP multicasting with Elixir to broadcast presence, and listen for peers, on a local network. I have found this approach us...
2 1198 0
New
First poster: malloryerik
Everyone outside of tech has heard of JavaScript, Java, Python, Ruby and even .Net, but few if any have heard of F#. However, F# may be o...
43 1943 14
New
paulanthonywilson
Following up on the previous post on using UDP multicasting to broadcast and detect peers on a network, I create a registry of those peer...
2 1706 0
New
First poster: AstonJ
They expect you to make a onepage application (SPA) The polaris design system officially only supports react Integration with the s...
26 1527 11
New
First poster: bot
Too long have we hustled to deploy Clojure websites. Too long have we spun up one server instance per site. Too long have reminisced abou...
0 1173 0
New
First poster: bot
I wrote Python for the last 10 years, and I always tend to write code in a “functional” way - map, filter, lambda and so on, it makes me ...
0 1042 0
New
wolf4earth
Charles Max Wood takes the lead this week. He and Adi Iyengar discuss what Top End Devs are and what people should be doing to become Top...
16 1663 5
New
RudManusachi
Hi there! Recently I was playing around with extracting and updating data in the DB and for fun challenged myself to try to implement a ...
8 1152 1
New
fullstackplus
The Ruby ecosystem is rich with tools that make us developers more productive at what we do. Both Rails and Sinatra have been used to bui...
21 1010 10
New
GoulvenClech
Hi everyone :wave: I’m excited to share an article detailing how we have reorganized our Elixir/Phoenix project’s directory structure. W...
9 768 3
New

Other popular topics Top

Devtalk
Hello Devtalk World! Please let us know a little about who you are and where you’re from :nerd_face:
476 5781 112
New
Devtalk
Reading something? Working on something? Planning something? Changing jobs even!? If you’re up for sharing, please let us know what you’...
1033 17470 383
New
siddhant3030
I’m thinking of buying a monitor that I can rotate to use as a vertical monitor? Also, I want to know if someone is using it for program...
51 4319 20
New
dasdom
No chair. I have a standing desk. This post was split into a dedicated thread from our thread about chairs :slight_smile:
177 8632 77
New
PragmaticBookshelf
Rust is an exciting new programming language combining the power of C with memory safety, fearless concurrency, and productivity boosters...
116 8174 31
New
New
AstonJ
In case anyone else is wondering why Ruby 3 doesn’t show when you do asdf list-all ruby :man_facepalming: do this first: asdf plugin-upd...
11 5382 4
New
AstonJ
If you get Can't find emacs in your PATH when trying to install Doom Emacs on your Mac you… just… need to install Emacs first! :lol: bre...
4 4891 0
New
AstonJ
Was just curious to see if any were around, found this one: I got 51/100: Not sure if it was meant to buy I am sure at times the b...
4 3745 1
New
PragmaticBookshelf
Develop, deploy, and debug BEAM applications using BEAMOps: a new paradigm that focuses on scalability, fault tolerance, and owning each ...
40 2292 21
New