Elixir's with (or within you without you :))

Posted by Richard Lucas on Feb 25 2018

Before we get with it…A quick pattern matching review

In Elixir, the = operator is actually called the match operator. While, we can usually see it as assignment, in Elixirland, it’s much easier if we can see it as pattern matching [1].

1
2
3
4
5
6
7
8
iex> x = 1
1
iex> x
1
iex> 1 = x
1
iex> 2 = x
** (MatchError) no match of right hand side value: 1

Another quick example (taken from Elixir docs) [2]:

1
2
3
4
iex> {:ok, result} = {:ok, 13}
{:ok, 13}
iex> result
13

And in the context of program (example_1.exs):

1
2
3
4
5
6
7
8
9
10
11
defmodule Example1 do
def say_hello("hello") do
"What's shaking Meetup?"
end
def say_hello("hola") do
"Hola mi amigos"
end
def say_hello(msg) do
"I don't understand #{msg}"
end
end

Run $ iex example_1.exs:

1
2
3
4
5
6
iex(1)> Example1.say_hello("hi")
"I don't understand hi"
iex(2)> Example1.say_hello("hello")
"What's shaking Meetup?"
iex(3)> Example1.say_hello("hola")
"Hola mi amigos"

Quick sidebar note from the Elixir docs:

In addition to the Elixir file extension .ex, Elixir also supports .exs files for scripting. Elixir treats both files exactly the same way, the only difference is in intention. .ex files are meant to be compiled while .exs files are used for scripting. When executed, both extensions compile and load their modules into memory, although only .ex files write their bytecode to disk in the format of .beam files [3].

Almost with it…A quick review of pipes

I’m hoping you have some experience with Unix pipes as these are similar. From the docs, “The |> symbol…is the pipe operator: it takes the output from the expression on its left side and passes it as the first argument to the function call on its right side.” [4] They allow the ability to Stream from one operation to the next.

An example:

1
2
3
4
1..500 |>
Enum.map(fn x -> x / 2 end) |>
Enum.filter(fn x -> x > 200 end) |>
Enum.count

What is with?

The with operator is a control flow mechanism that allows a sequence of operations to return a value or the ability to break out of that sequence.

Let’s look at some examples from Jose:

1
2
3
4
with {:ok, x} <- ok(1),
{:ok, y} <- ok(2),
do: {:ok, x + y}
#=> {:ok, 3}

If they all match in the sequence, we’re done.

1
2
3
4
with {:ok, x} <- ok(1),
{:ok, y} <- error(2),
do: {:ok, x + y}
#=> {:error, 2}

Here, because they don’t, the sequence is aborted and an error is returned.