Skip to content

Instantly share code, notes, and snippets.

@tuomasj
Last active February 8, 2018 18:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tuomasj/577405f8d41353178c0c582fc19f5503 to your computer and use it in GitHub Desktop.
Save tuomasj/577405f8d41353178c0c582fc19f5503 to your computer and use it in GitHub Desktop.

Three cool things about Elixir

Here we scratch the surface of Elixir programming language from three different places. We are not going do a deep plunge, just three things that we think are cool. If this sparkles your intrest for more information, there is few links at the bottom of this blog post.

Pipe-operator

In Elixir, you can nest function calls in two ways:

Traditional way

Split string into an array (traditional way)

iex> String.split("Secret society of experienced programmers")
["Secret", "society", "of", "experienced", "programmers"]

Uppercase the string and then split it into an array:

iex> String.split(String.upcase("Secret society of experienced programmers"))
["SECRET", "SOCIETY", "OF", "EXPERIENCED", "PROGRAMMERS"]

Using Pipe-operator

The pipe-operator is quite similar to Unix pipe-operator. You pass the expression to the next expression. Here is how it looks with pipe-operator:

Split string into an array with pipe-operator

iex> "Secret society of experienced programmers" |> String.split
["Secret", "society", "of", "experienced", "programmers"]

Uppercase a string and split it into an array with pipe-operator

iex> "Secret society of experienced programmers" |> String.upcase |> String.split
["Secret", "society", "of", "experienced", "programmers"]

Where it really shines

When writing web applications, controller actions become more readable with pipe-operators:

def new(conn, %{"token" => token}) do
  user = Resource.find_user_by_token(token)
  
  conn
  |> assign(:token, token)
  |> assign(:email, Map.get(user, :email))
  |> render("new.html")
end

Pattern Matching

There are many ways to do pattern matching, but using pattern matching with a map of arguments for a function is really cool. With pattern matching, it is guaranteed that you have the parameters you are expecting. It means less if-clauses.

def invite(%{"email" => email, "token" => token}) do
  “Welcome #{email}! Your token is #{token}”
end

def invite(%{"email" => email) do
  “Welcome #{email}!”
end

Some other ways to do pattern matching:

case my_complex_function() do
  {:ok, str } -> str
  {:error, _} -> nil
end

Fetching value from a Map

iex> args = %{name: "Bill", email: "bill@localhost"}
iex> %{:name => name} = args
iex> name
"Bill"

Asynchronous Function Calls

Elixir is built on top of Erlang VM (BEAM) so all concurrent operations are Elixir’s bread and butter. Erlang was originally designed for telephone call routing applications back in the 80’s and 90’s by Ericsson.

Erlang applications are set of processes. Erlang processes are very lightweight to create and destroy. They share no resources with other processes and they either do their purpose or fail completely. The philosophy with error handling is pretty simple: when error occurs, just kill the process.

Elixir follows the same philosophy. Small, independent processes doing their given task and when finished, they return the value to parent process and cease to exist.

Learn more

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment