Chapter 1. Getting Comfortable
The easiest place to start learning Elixir is in Interactive Elixir, IEx. This command-line interface is a cozy place to get started and a good place to start figuring out what works and what doesn’t work in Elixir. Its features will spare you headaches later, so settle in!
Because Elixir runs on top of Erlang, you’ll need to install Erlang on your system first, and then install Elixir.
If you’re on Windows, installing Erlang is easy. Download the Windows binary file, run the installer, and you’re set. If you are a brave beginner tackling your first programming language, this is easily your best bet.
On Linux or macOS, you may be able to download the source file and compile it. On macOS you should be able to unzip and untar it and then, from the directory created by the untarring, run
sudo make install. However, that simple sequence works only if you have the right files installed, and it can give you mysterious errors if they aren’t. In particular, Apple’s shift to the LLVM compiler in newer versions of XCode instead of GCC makes it less likely that GCC will be on newer macOS systems, and Erlang needs GCC.
You can ignore the error about FOP, which Erlang uses to generate PDF documentation you can download elsewhere. Also, on newer Macs, you’ll get an error at the end that wxWidgets doesn’t work on 64-bit macOS. For now, ignore this too.
If the compilation approach doesn’t work or isn’t for you, Erlang Solutions offers a number of installs. Also, many different package managers (Debian, Ubuntu, MacPorts, Homebrew, and so on) include Erlang. It may not be the very latest version, but having Erlang running is much better than not having Erlang running. They do tend to make it run on the latest version of various operating systems, so if you have installation problems, look closely at their requirements.
Erlang is increasingly part of the default installation on many systems, including Ubuntu, largely thanks to the spread of CouchDB.
Once you have Erlang installed, you should be able to download a precompiled version of Elixir or the GitHub source. Some package managers are starting to support Elixir, including Homebrew. The code in this book should work with Elixir 1.3.0.
Then you need to set your path so that it can find elixir/bin.
Elixir’s instructions for setup are organized into a tutorial.
Firing It Up
Go to the command line (or shell, or terminal) and type
mix new first_app. This will invoke Elixir’s Mix tool, which “provides tasks for creating, compiling, and testing Elixir projects, managing its dependencies, and more.” In this case, the command you type creates a new, empty project in a directory named first_app:
$ mix new first_app * creating README.md * creating .gitignore * creating mix.exs * creating config * creating config/config.exs * creating lib * creating lib/first_app.ex * creating test * creating test/test_helper.exs * creating test/first_app_test.exs Your Mix project was created successfully. You can use "mix" to compile it, test it, and more: cd first_app mix test Run "mix help" for more commands. $
Rather than compiling and testing the empty project, go into the first_app directory and start the IEx shell with these commands:
$ cd first_app $ iex -S mix
You’ll see something like the following code sample, likely with a cursor next to the
iex(1)> prompt. Note that where necessary in the book, some of the longer lines have been reformatted to fit on the page:
$ cd first_app [david@localhost first_app]$ iex -S mix Erlang/OTP 19 [erts-8.0] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] Compiling 1 file (.ex) Generated first_app app Interactive Elixir (1.3.1) - press Ctrl+C to exit (type h() ENTER for help) iex(1)>
You’re in Elixir! (The first line about Erlang reflects that Elixir runs within Erlang. Don’t worry about that part!)
Before moving on to the excitement of programming Elixir, it’s always worth noting how to quit. The shell suggests Ctrl+C, which will bring you to a menu. If you press “a” in that menu, IEx will stop, and you’ll see whatever prompt you had before starting IEx:
iex(1)> BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded (v)ersion (k)ill (D)b-tables (d)istribution a $
iex(1)> h() # IEx.Helpers 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 function to invoke the documentation for any Elixir module or function: ┃ h Enum ┃ h Enum.map ┃ h Enum.reverse/1 You can also use the i function to introspect any value you have in the shell: ┃ i "hello" There are many other helpers available: ... :ok
So what have you done here? You’ve issued an
iex command, calling a helper function,
h(), that provides you with some basic help information. It printed a lot of information to the screen and then ended, returning
Moving Through Text and History
If you explore the shell, you’ll find that many things work the way they do in other shells, or in Emacs. The left and right arrow keys move you backward and forward through the line you’re editing. Some of the key bindings echo those of the Emacs text editor. Ctrl+A will take you to the beginning of a line, while Ctrl+E will take you back to the end of the line. If you get two characters in the wrong sequence, pressing Ctrl+T will transpose them.
Also, as you type a closing parenthesis, square bracket, or curly brace, the cursor will highlight the corresponding opening parenthesis, square bracket, or curly brace.
Moving Through Files
IEx does understand filesystems to some extent, because you may need to move through them to reach the files that will become part of your program. The commands have the same names as Unix commands but are expressed as functions. IEx starts wherever you opened the shell, and you can figure out where that is with
iex(1)> pwd() /Users/elixir/code/first_app :ok
iex(2)> cd ".." /Users/elixir/code :ok iex(3)> cd "first_app" /Users/elixir/code/first_app :ok
iex(1)> 2 + 2 4 iex(2)> 27 - 14 13 iex(3)> 35 * 42023943 1470838005 iex(4)> 4 * (3 + 5) 32 iex(5)> 200 / 15 13.333333333333334
The first three operators are addition (
+), subtraction (
-), and multiplication (
*), which work the same way whether you’re working with integer values or floating points. Parentheses let you modify the order in which operators are processed, as shown on line 4. (The normal order of operations is listed in Appendix A.) The fourth operator,
/, supports division where you expect a floating-point result (a number with a decimal part), as shown on line 5. You don’t have to put spaces around operators, but it can make your code more readable.
Functions are bits of logic that accept arguments and return a value. Mathematical functions are an easy place to start. For example, if you want an integer result (and have integer arguments), use the
div() function instead of the
/ operator, with
rem() to get the remainder, as shown on lines 6 and 7:
iex(6)> div(200,15) 13 iex(7)> rem(200, 15) 5 iex(8)> rem 200, 15 5
Line 8 demonstrates a feature of Elixir syntax: parentheses around the arguments to a function are optional. If you think they make your code clearer, use them. If you think they are just extra typing, don’t.
Elixir will interpret a space after the function name as the equivalent of the opening of a set of parentheses, with the parentheses assumed to close at the end of the line. When this produces unexpected results, Elixir may ask in an error message that you “do not insert spaces in between the function name and the opening parentheses.”
Elixir will accept integers in place of floats, but floats are not always welcome where integers are used. If you need to convert a floating-point number to an integer, you can use the
round() built-in function:
iex(9)> round 200/15 13
round() function drops the decimal part of the number. If the decimal part was greater than or equal to .5, it increases the integer part by 1, rounding up. If you’d rather just drop the decimal part completely to get the integer part, use the
iex(10)> 4*v(9) 52
The result on line 9 was
If you want to do more powerful calculations, Elixir lets you use Erlang’s
math module, which offers pretty much the classic set of functions supported by a scientific calculator. These functions return floating-point values. The constant pi is available as a function,
:math.pi(). Trigonometric, logarithmic, exponential, square root, and (except on Windows) even the Gauss error functions are readily available. (The trigonometric functions take their arguments in radians, not degrees, so be ready to convert if necessary.) Using these functions is a little verbose because of the need to prefix them with
:math., but it’s still reasonably sane.
For example, to get the sine of zero radians, you could write:
iex(11)> :math.sin(0) 0.0
Note that the result is
0.0, not just
0, indicating that the number is floating point. (And yes, you could have written
:math.sin 0 without the parentheses.)
To calculate the cosine of pi and 2pi radians, you’d write:
iex(12)> :math.cos(:math.pi()) -1.0 iex(13)> :math.cos(2 * :math.pi()) 1.0
To calculate 2 taken to the 16th power, you’d use:
iex(14)> :math.pow(2,16) 65536.0
The full set of mathematical functions supported by Erlang’s
math module and accessible through Elixir is listed in Appendix A.
Numbers in Elixir
Elixir recognizes two kinds of numbers: integers and floating-point numbers (often called floats). It’s easy to think of integers as “whole numbers,” with no decimal point, and floats as “decimal numbers,” with a decimal point and some value to the right of the decimal.
1 is an integer, while
1.0 is a floating-point number.
However, it’s a little trickier than that. Elixir stores integers and floats in a very different way. Elixir lets you store massive integers, but whether they’re big or small, they are always precise. You don’t need to worry about their values being off by just a little.
Floats, on the other hand, cover a wide range of numbers but with limited precision. Elixir uses the 64-bit IEEE 754-1985 “double precision” representation. This means that it keeps track of about 15 decimal digits, plus an exponent. It can also represent some large numbers—powers up to positive or negative 308 are available—but because it tracks only a limited number of digits, results will vary a little more than may seem convenient, especially when you want to do comparisons:
iex(1)> 3487598347598347598437583475893475843749245.0 3.4875983475983474e42 iex(2)> 2343243.345435893850234543339545 2343243.3454358936 iex(3)> 0.0000000000000000000000000000023432432432432234232324 2.3432432432432235e-30
As you can see, some digits get left behind, and the overall magnitude of the number is represented with an exponent.
When you enter floating-point numbers, you must always also have at least one number to the left of the decimal point, even if it’s zero. Otherwise, Elixir reports a syntax error—it doesn’t understand what you’re doing:
iex(4)> .0000000000000000000000000000023432432432432234232324 ** (SyntaxError) iex:4: syntax error before: '.'
You can also write floats using the digits-plus-exponent notation:
iex(4)> 2.923e127 2.923e127 iex(5)> 7.6345435e-231 7.6345435e-231
Floats’ lack of precision can cause anomalous results. For example, the sine of zero is zero, and the sine of pi is also zero. However, if you calculate this in Elixir, you won’t quite get to zero with the float approximation Elixir provides for pi:
iex(6)> :math.sin(0) 0.0 iex(7)> :math.sin(:math.pi()) 1.2246467991473532e-16
If Elixir’s representation of pi went further, and its calculations of pi went further, the result for line 7 would be closer to zero.
If you need to keep track of money, integers are going to be a better bet. Use the smallest available unit—cents for US dollars, for instance—and remember that those cents are 1/100 of a dollar. (Financial transactions can go to much smaller fractions, but you’ll still want to represent them as integers with a known multiplier.) For more complex calculations, though, you’ll want to use floats, and just be aware that results will be imprecise.
Elixir supports integers in a few bases other than 10. For example, if you wanted to specify the binary value of 1010111, you could write:
iex(8)> 0b01010111 87
Elixir reports back with the base-10 value of the number. Similarly, you can specify hexadecimal (base-16) numbers by using
x instead of
iex(9)> 0xcafe 51966
To make any of these numbers negative, just put a minus sign (
-) in front of them. This works with integers, numbers in hex or binary, and floats:
iex(10)> -1234 -1234 iex(11)> -0xcafe -51966 iex(12)> -2.045234324e6 -2045234.324
Working with Variables in the Shell
v() function lets you refer to the results of previous expressions, but it’s not exactly convenient to keep track of result numbers, and the
v() function works only in the shell. It isn’t a general-purpose mechanism. A more reasonable solution stores values with textual names, creating variables.
Elixir variable names begin with a lowercase letter or an underscore. Normal variables start with a lowercase letter, whereas “don’t care” variables start with an underscore (see “Underscoring That You Don’t Care”). For now, stick with normal variables. You assign a value to a variable using a syntax that should be familiar from algebra or other programming languages, here with
n as the variable:
iex(1)> n=1 1
To see the value of a variable, just type its name:
iex(2)> n 1
Elixir, unlike many other functional programming languages (including Erlang), will let you assign
n a new value:
iex(3)> n=2 2 iex(4)> n=n+1 3
Elixir makes the righthand side of an expression, after the
=, match the lefthand side. It will assign a new value to
n if you ask it to do so, and will even use the old value of
n on the righthand side to calculate a new value for
n=n+1 means “assign the value
n+1, which is
When you assign a value to a variable, you should make sure that all the calculations are on the right side of the equals sign. Even though we know that
m should be
2*m = 3*4, Elixir doesn’t:
iex(5)> 2*m=3*4 ** (CompileError) iex:12: illegal pattern
IEx will remember your variables until you quit or tell it to forget them.
iex(6)> distance = 20; gravity = 9.8 9.8 iex(7)> distance 20 iex(8)> gravity 9.8
IEx will only report the value of the last statement, but as you can see on lines 19 and 20, all the values were assigned.
Before moving on to the next chapter, which will introduce modules and functions, spend some time playing in IEx. The experience, even at this simple level, will help you move forward. Use variables, and see what happens with large integers. Elixir supports large numbers very well. Try mixing numbers with decimal values (floats) and integers in calculations, and see what happens. Nothing should be difficult yet.