Hacker News new | ask | show | jobs
by vlunkr 1159 days ago
I'm in the same boat with Elixir. I love many aspects of the language, but it borrows the fast-and-loose type ecosystem of ruby.

nil is an especially big problem. Any value could be nil, and this will absolutely bite you over and over. nil even allows you to use square brackets for some reason (some_nil_value[:some_key]) which is a great way to disguise the actual issue.

There is optional type checking with Dialyzer, which is good but has some problems. The warning output can be really hard to read, and unless you're diligent in using it across most of your project, it's not very useful, because you'll end up with 'any' values all over.

2 comments

I disagree. Any value could be nil, but any value could be 5, too. In fact, nil is just like any other atom. Elixir shines when you lean on pattern matching as much as possible. Your functions should unpack as much as possible within the function definition, frankly the "if" macro is completely superfluous to case and in rare cases cond. You'll find that you match the data you want, and thus reject anything else.

Square bracket dictionary accesses are a code smell, because you should be using %{^key = val} = dict or Map.fetch(map, key) or rarely Map.fetch!(map, key).

If you do that, managing typing in Elixir just boils down to defining structs to differentiate cases where dictionary A and dictionary B contain similar keys but strictly are not interchangeable.

Any errors these techniques could catch would have to happen during runtime, not at compile time, and this is a huge and key difference. In my experience having the type errors being caught at compile time is an incredible boost to productivity. I just write code then hit Ctrl+S and the compiler tells me what I got wrong, instead of all the hassle of having to write functions a line at a time, flip to IEx, run, inspect some intermediary value to make sure it works as intended, while trying to keep so many things in my head at once, which at times can be just overwhelming and highly frustrating.
Elixir is incredibly consistent with how it uses nil. It does take a bit of work -- you have to really pay attention to the convention of fetch! vs fetch vs get -- and often times library maintainers are not... always the best at that... but for all the problems that dynamic languages has, nil in elixir is pretty low on the list. I think I get bitten by maybe one a year, and it causes the sporadic report on sentry, and then I go and fix it, and that's that.

That access acts on nil is unfortunate, but it's necessary for things like get_in.

> That access acts on nil is unfortunate, but it's necessary for things like get_in.

Ah, that explains it at least. Other atoms don't implement the access behavior.