Running Elixir

In this book, I show a terminal session like this:

 $ ​​echo​​ ​​Hello,​​ ​​World
 Hello, World

The terminal prompt is the dollar sign, and the stuff you type follows. (On your system, the prompt will likely be different.) Output from the system is shown without highlighting.

iex—Interactive Elixir

To test that your Elixir installation was successful, let’s start an interactive Elixir session. At your regular shell prompt, type iex.

 $ iex
 Erlang/OTP 20 [erts-9.1] [source] [64-bit] [smp:4:4] [ds:4:4:10]
  [async-threads:10] [hipe] [kernel-poll:false]h
 Interactive Elixir (x.y.z) - press Ctrl+C to exit (type h() ENTER for h
 elp)
 iex(1)>

(The various version numbers you see will likely be different—I won’t bother to show them on subsequent examples.)

Once you have an IEx prompt, you can enter Elixir code and you’ll see the result. If you enter an expression that continues over more than one line, IEx will prompt for the additional lines with an ellipsis (…).

 iex(1)>​ 3 + 4
 7
 iex(2)>​ String.reverse ​"​​madamimadam"
 "madamimadam"
 iex(3)>​ 5 *
 ...(3)>​ 6
 30
 iex(4)>

The number in the prompt increments for each complete expression executed. I’ll omit the number in most of the examples that follow.

There are several ways of exiting from IEx—none are tidy. The easiest two are typing Ctrl-C twice or typing Ctrl-G followed by q and Return. On some systems, you can also use a single Ctrl-\.

IEx Helpers

IEx has a number of helper functions. Type h (followed by Return) to get a list:

 iex> h
  IEx.Helpers
 
 Welcome to Interactive Elixir. You are currently seeing the documentation
 for the module IEx.Helpers which provides many helpers to make Elixir's
 shell more joyful to work with.
 
 This message was triggered by invoking the helper h(), usually referred to
 as h/0 (since it expects 0 arguments).
 
 You can use the h/1 function to invoke the documentation for any Elixir
 module or function:
 
  iex> h(Enum)
  iex> h(Enum.map)
  iex> h(Enum.reverse/1)
 
 You can also use the i/1 function to introspect any value you have in the
 shell:
 
  iex> i("hello")
 
 There are many other helpers available, here are some examples:
 
 • b/1 - prints callbacks info and docs for a given module
 • c/1 - compiles a file into the current directory
 • c/2 - compiles a file to the given path
 • cd/1 - changes the current directory
 • clear/0 - clears the screen
 • exports/1 - shows all exports (functions + macros) in a module
 • flush/0 - flushes all messages sent to the shell
 • h/0 - prints this help message
 • h/1 - prints help for the given module, function or macro
 • i/0 - prints information about the last value
 • i/1 - prints information about the given term
 • ls/0 - lists the contents of the current directory
 • ls/1 - lists the contents of the specified directory
 • open/1 - opens the source for the given module or function
  in your editor
 • pid/1 - creates a PID from a string
 • pid/3 - creates a PID with the 3 integer arguments passed
 • ref/1 - creates a Reference from a string
 • ref/4 - creates a Reference with the 4 integer arguments
  passed
 • pwd/0 - prints the current working directory
 • r/1 - recompiles the given module's source file
 • recompile/0 - recompiles the current project
 • runtime_info/0 - prints runtime info (versions, memory usage, stats)
 • v/0 - retrieves the last value from the history
 • v/1 - retrieves the nth value from the history
 
 Help for all of those functions can be consulted directly from the command
 line using the h/1 helper itself. Try:
 
  iex> h(v/0)
 
 To list all IEx helpers available, which is effectively all exports
 (functions and macros) in the IEx.Helpers module:
 
  iex> exports(IEx.Helpers)
 
 This module also includes helpers for debugging purposes, see IEx.break!/4
 for more information.
 
 To learn more about IEx as a whole, type h(IEx).

In the list of helper functions, the number following the slash is the number of arguments the helper expects.

Probably the most useful is h itself. With an argument, it gives you help on Elixir modules or individual functions in a module. This works for any modules loaded into IEx (so when we talk about projects later on, you’ll see your own documentation here, too). For example, the IO module performs common input/output functions. For help on the module, type h(IO) or h IO:

 iex>​ h IO ​# or...
 iex>​ h(IO)
 
 Functions handling IO.
 
 Many functions in this module expect an IO device as argument. An IO device
 must be a PID or an atom representing a process. For convenience, Elixir
 provides :stdio and :stderr as shortcuts to Erlang's :standard_io and
 :standard_error....

This book frequently uses the puts function in the IO module, which in its simplest form writes a string to the console. Let’s get the documentation:

 iex>​ h IO.puts
  def puts(device \\ :stdio, item)
 
 Writes item to the given device, similar to write/2, but adds a
 newline at the end.
 
 By default, the device is the standard output. It returns :ok if it
 succeeds.
 
 ## Examples
 
  IO.puts "Hello, World!"
  #=> Hello, World!
 
  IO.puts :stderr, "error"
  #=> error

Another informative helper is i, which displays information about a value:

 iex>​ i 123
 Term
  123
 Data type
  Integer
 Reference modules
  Integer
 Implemented protocols
  IEx.Info, Inspect, List.Chars, String.Chars
 
 iex>​ i ​"​​cat"
 Term
  "cat"
 Data type
  BitString
 Byte size
  3
 Description
  This is a string: a UTF-8 encoded binary. It's printed surrounded by
  "double quotes" because all UTF-8 encoded codepoints in it are printable.
 Raw representation
  <<99, 97, 116>>
 Reference modules
  String, :binary
 Implemented protocols
  IEx.Info, Collectable, Inspect, List.Chars, String.Chars
 
 iex>​ i %{ ​name:​ ​"​​Dave"​, ​likes:​ ​"​​Elixir"​ }
 Term
  %{likes: "Elixir", name: "Dave"}
 Data type
  Map
 Reference modules
  Map
 Implemented protocols
  IEx.Info, Collectable, Enumerable, Inspect
 
 iex>​ i Map
 Term
  Map
 Data type
  Atom
 Module bytecode
  bin/../lib/elixir/ebin/Elixir.Map.beam
 Source
  lib/elixir/lib/map.ex
 Version
  [234303838320399652689109978883853316190]
 Compile options
  []
 Description
  Use h(Map) to access its documentation.
  Call Map.module_info() to access metadata.
 Raw representation
  :"Elixir.Map"
 Reference modules
  Module, Atom
 Implemented protocols
  IEx.Info, Inspect, List.Chars, String.Chars

IEx is a surprisingly powerful tool. Use it to compile and execute entire projects, log in to remote machines, and access running Elixir applications.

And, if you happen to include the occasional bug in your code (deliberately, of course), IEx has a simple debugger. We’ll talk about it when we look at tooling.

Customizing iex

You can customize IEx by setting options. For example, I like showing the results of evaluations in bright cyan. To find out how to do that, I used this:

 iex>​ h IEx.configure
 def configure(options)
 
 Configures IEx.
 
 The supported options are: :colors, :inspect, :default_prompt,
 :alive_prompt and :history_size.
 
 Colors
 
 A keyword list that encapsulates all color settings used by the shell. See
 documentation for the IO.ANSI module for the list of supported colors and
 attributes.
 
 The value is a keyword list. List of supported keys:
 
 • :enabled - boolean value that allows for switching the coloring
  on and off
 • :eval_result - color for an expression's resulting value
 • :eval_info - … various informational messages
 • :eval_error - … error messages
 • :stack_app - … the app in stack traces
 • :stack_info - … the remaining info in stack traces
 • :ls_directory - … for directory entries (ls helper)
 • :ls_device - … device entries (ls helper)
 
  . . .

I then created a file called .iex.exs in my home directory, containing

 IEx.configure ​colors:​ [ ​eval_result:​ [ ​:cyan​, ​:bright​ ] ]

If your IEx session looks messed up (and things such as [33m appear in the output), it’s likely your console does not support ANSI escape sequences. In that case, disable colorization using

 IEx.configure ​colors:​ [​enabled:​ false]

You can put any Elixir code into .iex.exs.

Compile and Run

Once you tire of writing one-line programs in IEx, you’ll want to start putting code into source files. These files will typically have the extension .ex or .exs. This is a convention—files ending in .ex are intended to be compiled into bytecodes and then run, whereas those ending in .exs are more like programs in scripting languages—they are effectively interpreted at the source level. When we come to write tests for our Elixir programs, you’ll see that the application files have .ex extensions, whereas the tests have .exs because we don’t need to keep compiled versions of the tests lying around.

Let’s write the classic first program. Go to a working directory and create a file called hello.exs.

intro/hello.exs
 IO.puts ​"​​Hello, World!"

That example shows how most of the code listings in this book are presented. The bar before the code itself shows the path and file name that contains the code. If you’re reading an ebook, you’ll be able to click on this to download the source file. You can also download all the code by visiting the book’s page on our site and clicking on the Source Code link.[2]

images/source_code.png

Source file names are written in lowercase with underscores. They will have the extension .ex for programs that you intend to compile into binary form, and .exs for scripts that you want to run without compiling. Our “Hello, World” example is essentially throw-away code, so we used the .exs extension for it.

Having created our source file, let’s run it. In the same directory where you created the file, run the elixir command:

 $ ​​elixir​​ ​​hello.exs
 Hello, World!

We can also compile and run it inside IEx using the c helper:

 $ iex
 iex>​ c ​"​​hello.exs"
 Hello, World!
 []
 iex>

The c helper compiled and executed the source file. The [] that follows the output is the return value of the c function—if the source file had contained any modules, their names would have been listed here.

The c helper compiled the source file as freestanding code. You can also load a file as if you’d typed each line into IEx using import_file. In this case, local variables set in the file are available in the IEx session.

As some folks fret over such things, the Elixir convention is to use two-column indentation and spaces (not tabs).