Elixir's biggest gotchas?

The thing that confused me the most in the beginning was the syntactic sugar for Keyword lists. I kept seeing these odd things in the options list for functions and I had no idea what they really were.

IO.inspect Process.list, width: 40

I cargo culted a lot of code until I actually made the connection that line is really.

IO.inspect(Process.list, [{:width , 40}])

10 Likes

I have to say that sometimes some of the syntactic sugar can make things a little more difficult to mentally parse for me. Maybe that’s just me though.

6 Likes

Yeah, the keyword lists sugar for function arguments gets me often. Just have to get used to it I guess.

2 Likes

Agreed on this one. Elixir used to have a ListDict module that was a sort of “superclass” of the current Keyword module that helped to make that explicit. However, once Erlang got large map support, it because superfluous. Now the leap from list to Keyword list has no intermediate step.

The implicit handling of it as the final param in a function call (reminiscent of Ruby) further adds to its mystical quality.

1 Like

… And on top of that, the order of keywords does matter.

def foo(name: name, type: type) will not be matched when calling foo(type: "elephant", name: "Dumbo").

12 Likes

Wow, that doesn’t stop to look confusing no matter how much I look at it :slight_smile: I was actually wondering if something like that is possible, but now that I see it I’m not sure I’d like to know :slight_smile:

Btw, where did you stumble upon that?

4 Likes

Most likely in this situation: Pipe operator and functions (not function calls)

i.e. for an ad hoc parameter reorder to continue the current chain (not recommended).

3 Likes

Y was using to restructure the return value from previous function, but better to write a separate function so things look clean.

3 Likes

If you haven’t seen pattern matching before, that might be difficult to get used to.
This isn’t really a gotcha - it’s one of Elixir’s strengths of course :slight_smile: , but someone new to Elixir would find it difficult to understand a lot of code if they’re unfamiliar with pattern matching.

3 Likes

3 things I have noticed when giving courses[*] that people coming from a non-functional background can have problems with are immutable data, pattern matching, and recursion. But once you grasp them you never want to go back.

Robert

[*] It has mainly been erlang courses, and now elixir courses, but at this level they are the same.

10 Likes

I switch-hit between ruby and elixir all the time, and I’m constantly lamenting the lack of pattern matching now. I really don’t get how I did this for so long without it!

7 Likes

I’m not sure if this is a gotcha, but I find it difficult to read backtraces due to macros and/or anonymous functions.

Remembering the scoping rules. I’ve given up on that and now just assume everything creates a new scope… that seems to be the direction things are headed anyway.

Ruby muscle memory and spending minutes looking for where I forgot to type do.

The precedence of |> (also due to Ruby muscle memory and an unconscious desire for special syntax for functions who’s last argument is a function). I’ve definitely learned to heed the compiler’s warnings on this one… :slight_smile:

3 Likes

TIL you can pipe into an anonymous function… even though the syntax may be a little awkward.

I’m not sure if this qualifies as a ‘gotcha’ per se, but I personally struggled with getting a complete grasp of the syntax. I don’t mean being able to use the syntax productively but rather the process unraveling the different macros and sugar and the different ways they can be represented.

Keyword lists and macros have already been mentioned above, which is really what I think this boils down to, but I’m talking about things like:

def add(x, y) do
  x + y
end

Being the same as:

def add(x, y), do: x + y

Which can be:

def add(x, y), [do: x + y]

Which is really:

def add(x, y), [{:do, x + y}]

Which can be:

def(add(x, y), [{:do, x + y}])

And now it’s revealed that what looked like a ‘standard’ function definition statement with some parameters and a function body is actually itself a call to a function.

I think there is a piece that I’m still missing with the add(x, y) definition really being something more akin to a value than a call, and when/how that conversion from a call to a value gets handled.

This isn’t necessarily a hurdle that you need to get over in order to become productive, but before you understand what’s going on behind the syntax little things can bleed through that may seem strange.

6 Likes

Thanks

That was an interesting post and I learned something new today.

I sort of agree with you. My biggest gotcha with elixir is that there
are so many ways of doing the same thing and I have the habit of picking
the one which shots me in the foot!

Many of the examples don’t work. Many of the github projects, beyond the basic functionality that ships with Elixir itself, are abandoned or don’t work. It’s a huge problem when trying to evaluate how robust and mature the Elixir eco-system is for commercial adoption.

EDIT: Since I was asked for examples, I will list them here.

http://blog.rh-flow.de/2016/01/19/parallel-processing-of-csv-in-elixir-and-golang/
https://github.com/jordipolo/dataframe

EDIT 2: My interest is in building a multi-node system that can do distributed processing of data in a ruby-style functional programming language. Data would enter this system via CSVs and Excel files (not just databases) and do extensive number crunching on all cores.

2 Likes

Can you please be a bit more constructive and show us some examples of “basic things on github that don’t work”?

When I came to elixir, roughly at the edge of 1.0, yes I had this feeling as well, since I nearly found pre-1.0 stuff that didn’t work anymore with 1.0. But this happens.

This happened to me with rust as well, and also happens with ruby every now and then after there was a new “major” (in the sense of massive changes, not versioning schema) update.

Today, most of the old tutorials simply vanished from the net, or they have been updated. Or one can simply see by the date, that they probably won’t help anymore.

You’re not missing any piece, except for: def/2 is not a function, it’s a macro, thats why add(x, y) is not a call to a function, and yes the AST for it’s definition. You can give it a check on Kernel.def/2 documentation.

BTW, for me, this is one of the most awesome gotchas about Elixir: documentation as a “first class citizen”, if you allow me to pervert a little bit the “first class citizen” term. However, elixir documentation is just awesome, and having them offline, and easily, with the h/1 function on iex is just wonderful. This made my learning experience a lot faster and softer!

5 Likes

Upvote for verging cargo-cult :smiley:

there are two points here that could be added to Elixir Gotchas and Common Issues Wiki

'foo' != "foo": Elixir's biggest gotchas? - #10 by josevalim
keyword lists are just sugar: Elixir's biggest gotchas? - #12 by bbense

1 Like