Tips & tricks for IEx - Elixir's interactive shell
When building an application with Elixir and Phoenix you inevitably spend a lot
of time with
IEx, Elixir’s wonderful interactive shell, testing things out.
Maybe you quickly need to update or delete a database record? Maybe you need to test out a pipeline of functions you have?
Or just come up with the best way to transform that list of data you have.
Either way having
IEx at disposal is extremely helpful.
We will, in this article, list a couple of tips and tricks that we have picked up
along the way while using
IEx. Some of these might already be familiar to you,
but maybe some are new to you and can help you get more productive and/or ease your day.
While inside the
IEx maybe you need to use a function that lives in a module with a very long
and nested name? Let’s see an example of how that could look like. Imagine that we have are building
an application for recipes. A recipe likely contains ingredients but also steps to instruct how
to follow the recipe.
The module name for the ingredients would likely be something like
MyPrettyLongAppName.Recipes.Ingredient and for steps
Now imagine that you want to see if a step contains the data you imagine in the
you would do something like this:
iex(1)> MyPrettyLongAppName.Recipes.Step |> MyPrettyLongAppName.Repo.get("some-unique-id")
That would be very cumbersome to write if you need to do this every now and then. So maybe you are prepared and
know that you need to do this more than once today and you make an alias in the current
IEx session so that
you can access the module without having to write the full name:
iex(1)> alias MyPrettyLongAppName.Recipes.Step iex(2)> alias MyPrettyLongAppName.Repo iex(3)> Step |> Repo.get("some-unique-id")
But wouldn’t it be nice to have the modules that you occasionally have to use in
IEx always aliased?
Well you can! In the root of your project create a
.iex.exs file and just put your aliases in there!
Note the dot in the filename. You can of course do more than just put aliases in there, for example
import some modules and even bind variables that you can then access from the shell.
Now when you start your project with
iex -S mix or
iex -S mix phx.server
all your aliases and imports are ready to be used! You can read more in the iex.exs documentation.
Break out of expression
From time to time you inevitably get trapped in an unfinished expression inside the interactive shell without it being obvious what character that’s missing to complete the expression. Here’s a nasty, but probably not that unrealistic example:
iex(1)> ["ab iex(1)> ] iex(1)> iex(1)> " iex(1)> " iex(1)> ]
See how we are not able to get out of the expression? Instead of hitting
CTRL + C twice and start over
we can use
#iex:break to simply break our unfinished expression:
iex(1)> ["ab iex(1)> ] iex(1)> iex(1)> " iex(1)> " iex(1)> ] iex(1)> #iex:break ** (TokenMissingError) iex:2: incomplete expression iex(1)> "Phew, I'm free!" "Phew, I'm free!" iex(2)>
And now you can retry writing the expression or continue with something else with all your history still intact!
Bind or use last expression
Are you maybe coming to Elixir from the Ruby on Rails world? Then you’ve likely done something like this to bind the last expression to a variable in the Rails console:
irb> [1, 2, 3, 4, 5] => [1, 2, 3, 4, 5] irb> list = _ irb> list => [1, 2, 3, 4, 5]
To do the same thing in the
IEx shell you would do this:
iex(1)> ["Elixir", "Phoenix", "Liveview", "Ecto"] ["Elixir", "Phoenix", "Liveview", "Ecto"] iex(2)> list = v() ["Elixir", "Phoenix", "Liveview", "Ecto"] iex(3)> list ["Elixir", "Phoenix", "Liveview", "Ecto"]
v(n \\ -1) function returns the value of the
nth expression. As you can see the default argument
-1, which means if we don’t send it any arguments like in the example above it will return the
last expression. That means if we press
Enter inbetween the expression and when we want to bind it to a variable we have to do this:
iex(1)> "I want to bind this to a variable!" "I want to bind this to a variable!" iex(2)> nil iex(3)> my_string = v(-2) "I want to bind this to a variable!" iex(4)> my_string "I want to bind this to a variable!"
You can even continue a pipeline from the last expression:
iex(1)> "It's so much fun working with Elixir!" "It's so much fun working with Elixir!" iex(2)> |> String.upcase() "IT'S SO MUCH FUN WORKING WITH ELIXIR!" iex(3)> |> String.split() ["IT'S", "SO", "MUCH", "FUN", "WORKING", "WITH", "ELIXIR!"]
In the background it does this:
iex(1)> "It's so much fun working with Elixir!" "It's so much fun working with Elixir!" iex(2)> v() |> String.upcase() "IT'S SO MUCH FUN WORKING WITH ELIXIR!"
Bonus - shell history
A really annoying thing is to lose your history when exiting the
IEx shell. You can add history by starting the IEx-shell with
iex --erl "-kernel shell_history enabled". But more likely you would want to have this every time without having to explicitly write it. You can do that by adding it to your shell configuration.
For a Unix system you would add the below snippet to your
.zshrc file. For other systems take a look in the IEx documentation.
export ERL_AFLAGS="-kernel shell_history enabled"
Hopefully some of these tips were unknowed to you and can now help you in your day to day life, no matter if you use Elixir in your workplace or just playing around with it in your free time (and day dreaming about using it at your workplace).
Either way, thank your for taking the time to read this article! Be sure to come back later for a tips and tricks #2!