Elixir has been hyped in recent years as a programming language for modern Web development. If you want to learn Elixir go ahead and read few tips that I’m sharing with you to make your first experience with Elixir more appealing. After having built my first product (Retrochat - Retrospectives Slack bot) with Elixir I came to a conclusion that Elixir ecosystem is very big. You can read guides, books and documentations for a long time before you have a courage to jump in and start writing programs. My aim is to help you start writing Elixir ASAP, because the sooner you dive in, the faster you will learn it.

Disclaimer: This post’s intent isn’t to show you new cool tricks that will miraculously boost your development or learning time by 100%.

Learning Elixir

Resources

Books: There are many books, but I’m not gonna recommend you any. I read a few of the books, but I don’t think they are really necessary to get started. Although, I do recommended reading them at some point.

Internet resources: I’d start with Internet resources that are worth reading through:

  1. https://elixir-lang.org/getting-started/introduction.html
  2. https://elixirschool.com/
  3. https://elixir-lang.org/docs.html
  4. https://hexdocs.pm/elixir/Kernel.html

I’d recommend to get through basic language stuff(1,2 positions). Use docs(3,4 position) to read about the language and other tools in Elixir ecosystem. I think Elixir docs are very well written and you will learn a lot from them. Seriously, the docs are worth reading through if you are looking for details.

Learning path

In my opinion, you should start learning Elixir by getting to know syntax + stdlib + mix + Elixir features such as pattern matching, functions, structs, pipe operator, etc - you can find them listed in the mentioned resources above. That knowledge should be enough to write scripts and get to know the language better by actual practice. If scripts are not good enough for you, you can write some CLI programs.

I think understanding Elixir basics should be enough to start playing with Phoenix and Ecto and also writing your own first web apps. Phoenix is quite a beast, so it will take some time to learn it, especially, if you don’t know any MVCish framework. I’m gonna write another post on how to get started with Phoenix along with some tips.

REMEMBER NOT TO START WITH FRAMEWORK(PHOENIX) WITHOUT LEARNING ELIXIR. OTHERWISE YOU ARE GONNA FAIL HARD.

I haven’t mentioned OTP yet, because I think you don’t need to know it to write in Elixir. Be careful though, because a lot of packages (Phoenix included) use OTP heavily - after all it’s Elixir’s bread and butter.

There are also macros (meta programming). It’s worth knowing how macros work, because a lot of packages are using them. You don’t need to know meta programming to write your first programs, though. If you are only interested in Web dev, I’d say that you can get quite far without knowing how they work. I think you should stay away from macros before you get a good grasp of Elixir.

Just learn the basic Elixir and start writing programs! If you will need OTP/macros, you are gonna learn them then. I believe that practice is one of the best ways to learn and reading about OTP/macros is just gonna slow you down before trying ELIXIR.

This is my opinion. If you are learning Elixir because you need OTP, then do learn it immediately along with other features of Elixir.

Learn writing tests! ExUnit is pretty simple, there is no hard DSL like in some other testing frameworks. You just test public API(functions) from the modules you defined. Imo, totally worth it. I remember, wrapping my head around RSpec was very hard at first, because of that complex DSL and a lot of configuration code. I don’t think it’s a case in ExUnit. Test will feel like they are written in Elixir. You will learn both how to write tests for your Elixir code and how to write Elixir. Isn’t it SO GOOD!?

Learning through reading code

Don’t be afraid to look into source code on github. I think it’s quite good way to learn a language like Elixir. Code is really readable (if you skip macros), so you will learn patterns like piping, pattern matching, etc. faster. Additionally, you get to see how other developers use Elixir and you can try to mimic their style.

Personally, I recommend to check Awesome Elixir on Github. There is pretty big list of Elixir projects. If you are learning, look for libraries/programs that solve very specific problem, because probably there won’t be too much macros and OTP. It’s worth noting that many projects listed there are not longer maintained. It’s then your job to check if it’s worth learning from that source or not (big list of Issues could help you determine it).

Elixir ecosystem is pretty big and it may be hard to grasp all of it at once. Just focus on one thing at a time and learn it by writing code. Step by step and you will explore most of Elixir’s ecosystem and you will probably become pretty productive.

Errors? Questions? Where to find answers?

From my experience you will find a lot of solutions on stackoverflow but also at elixirforum.com - it’s worth using search over there. Sometimes answers to your questions will be available at Github.

Quick and easy installation

I recommend asdf. You should install elixir, erlang.

Code editor

Use Visual Studio Code. I guess it has one of the best Elixir support available, but I only tried Atom/Sublime/VSCode. There is also Vim and Emacs, but I haven’t tested them, so feel free to check their support for Elixir, if you know them best :)

VSCode plugins worth your time:
Most important one, for language support with formatter, linting, code completion, docs lookup and more: elixir-ls

For themes I use this plugin: dark-plus-elixir

For snippets: elixir-snippets

And for fast inserting module names into code (when you create a new file) I use: elixir-module-autoname

Commands

mix help
This command will list all available mix tasks in current directory.

mix hex.docs fetch
This will download all packages docs to browse them locally. You can then open them in web and it will look like hexdocs.pm (imo really good solution when your internet connection gets cut off)

iex -S [task]
This one will run task inside of iex, so you can use console for debugging. Very useful during development and writing tests.

mix format
It will format your code, just like prettier. Your code editor is probably gonna handle running this for you, though.

Packages

mix_test_watch
https://github.com/lpil/mix-test.watch
This package is pretty useful as it will run tests when files get changed. You can run it by issuing mix test watcher. Additionally, running test in Elixir is pretty fast, so you will get results almost instantly.

ex_unit_notifier
https://github.com/navinpeiris/ex_unit_notifier
This package will show desktop notification for ExUnit runs. It’s very useful when used with mix_test_watch.

ex_doc
https://github.com/elixir-lang/ex_doc
This package lets you build docs (that look like the ones on hexdocs.pm) for your project. Imo, it’s very cool to use it if you document your own code and want to introduce new developers to your code base.

credo
https://github.com/rrrene/credo
If you are used to static code analysis tools, this one is made for Elixir language.

Elixir interactive shell - iex

Can be used to test, learn and evaluate Elixir code.

Shell history

By default there is no shell history in IEX. If you exit IEX and open it again, you are not gonna be able to check previous commands. To fix that: you can run iex like this:

iex --erl "-kernel shell_history enabled"

or you can just export env variable:

export ERL_AFLAGS="-kernel shell_history enabled"

More info here

Recompiling code

Type recompile() inside of iex session to recompile your code. It’s useful when you are changing or debugging your code and you want to use new version of it.

Auto completion

You can autocomplete module names and function names by pressing tab.

iex(1)> E
Elixir         Enum           Enumerable     ErlangError    Exception
iex(2)> Enum.
EmptyError           OutOfBoundsError     all?/1
all?/2               any?/1               any?/2
[...]

Helpers

You can find full list of helpers here.

You can use i/0 and i/1 to get information about last value or given term:

iex(5)> 1
1
iex(6)> i
Term
  1
Data type
  Integer
Reference modules
  Integer
Implemented protocols
  IEx.Info, List.Chars, Inspect, String.Chars
iex(7)> i "b"
Term
  "b"
Data type
  BitString
Byte size
  1
[...]

Use v/0 and v/1 to get value of nth expression in the history.

iex(1)> 1
1
iex(2)> 2
2
iex(3)> 3
3
iex(4)> v # latest value
3
iex(5)> v(1) # look at value from iex(1)
1
iex(6)> v(2) # look at value from iex(2)
2

Configuration

You can configure IEx by IEx.configure/1. I recommend setting inspect mode to infinity. If you are dealing with huge data structures, like responses from 3rd API, you won’t be able to see whole output without setting limit to infinity.

IEx.configure [inspect: [limit: :infinity]]

.iex.exs file

You can define .iex.exs file in your project’s directory. In this file you can define modules, variables, aliases, etc. and they are gonna be available in your shell. This is very useful for aliasing modules, but also for configuring your iex properly (with IEx.configure/1). It can be also very useful to define functions that will help you with statistics, hot db fixes (like restoring some data), etc.

You can also have ~/.iex.exs file, which can be useful for global configuration. If you have both ~/.iex.exs and .iex.exs you can import it in .iex.exs like this:

# .iex.exs
import_file "~/.iex.exs"

...

You can find more about .iex.exs here.

Debugging

If you are running your application/task inside of iex, you can use IEX.pry for debugging, remember to require it though:

defmodule BrokenModule do
  def broken_function(a) do
    ...
    require IEx
    IEx.pry()
  end
end

To leave from pry you have to type respawn().

IO.inspect/2

I’d recommend to use IO.inspect/2 for debugging, because it’s much easier and faster to deal with. The data is immutable so you can see step by step how it gets transformed and you can spot a place where it doesn’t transform the way you want. You can also use IO.inspect/2 in pipelines:

# you have to require Integer, because Integer.is_even/1 is a macro.
require Integer
[2,5,6]
  |> IO.inspect(label: "Before check:")
  |> Enum.map(fn number -> Integer.is_even(number) end)
  |> IO.inspect(label: "After check")

Before check [2, 5, 6]
After check [true, false, true]

The end

Just like I said at the beginning, this knowledge is pretty basic, but it should let the beginners start coding faster :) If you liked this post, make sure to follow me on twitter, where you can find out about my next posts.