Tips & tricks for IEx - Elixir's interactive shell
Published 6 May 2022
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.
Autoload aliases
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 MyPrettyLongAppName.Recipes.Step
.
Now imagine that you want to see if a step contains the data you imagine in the IEx
shell,
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
require
or 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"]
The v(n \\ -1)
function returns the value of the n
th expression. As you can see the default argument
for n
is -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 .bashrc
/.zshrc
file. For other systems take a look in the IEx documentation.
export ERL_AFLAGS="-kernel shell_history enabled"
Conclusion
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!