Falling short, yet again, of my weekly blog goal, I’ll opt for a bi-monthly review of what’s going on and what has kept me from writing.

As if having a 4 month old baby and trying to cram as much daddy daughter time into the day wasn’t enough. In late August I accepted a job with a tiny web development agency in Salt Lake City. Accepting this offer gave me two weeks to move country, find housing, navigate the US’s draconian health care system and start the complex immigration process for my wife.

It’s been a very tumultuous time to say the least but the changes are a really good step in the right direction. I still feel quite unsettled but I hope as we start to accumulate more furniture other then two Ikea chairs our humble apartment will start to feel more like home.

On a far more interesting note one of the larger projects I’m working on is a Phoenix application. Before starting this job I had zero Elixir experience, and despite the “Ruby-like” syntax Elixir there is still a steep learning curve moving from the object oriented world to the functional one. Elixir comes with some really well thought out linguistic features such as pattern matching and function pipelines which I have not encountered before.

# Pipelines in action
# How a traditional map and filter may be constructed

iex(1)> num_list = [1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7]
iex(2)> add_five = Enum.map(num_list, fn x -> x + 5 end)
[6, 7, 8, 9, 10, 11, 12]
iex(3)> filtered_list = Enum.filter(add_five, fn x -> x >= 10 end)
[10, 11, 12]

# That’s one way of doing it, but with pipelines we can simply pass the result of the last function into
# the next function omitting the first argument the function would otherwise take.
# This allows us to be much more concise.

iex(1)> [1, 2, 3, 5, 6, 7] |> Enum.map(fn x -> x + 5 end) |> Enum.filter(fn x -> x >= 10 end)
[10, 11, 12]

# if you find writing `fn x -> x … end` a little tedious Elixir has a capture operator for creating these
# anonymous functions: &. So the syntax above would become Enum.map(num_list, & &1 + 5), which is what I
# almost exclusively use.

Both the map/2 and the filter/2 functions normally have an arity (the number of arguments a function takes) of two, but each is only being passed one argument (& &1 + 5 and & &1 >= 10) respectively. The pipe operator is smart enough to pass the result of the last function into the next one in the pipeline.

Elixir convention dictates that arity be listed after reverting to a function hence map/2 or filter/1 this is because Elixir relies heavily on pattern matching which allows you to declare multiple functions that do essentially the same thing.

def find_user(%{user_id} => user) do
	# do something with the user

def find_user(%{user_name} => user) do
	# do something with the user

def find_user(user, status) do
	# do something with the user based on their status

Above we have three functions called find_user the first two have an arity of 1 and the last has an arity of 2. This would be problematic in a lot of languages but this works in Elixir because of the language’s heavy use of pattern matching. When the find_user function is called it will look at how many arguments the function call is given, if it’s two find_user/2 will be called. If it’s only one then Elixir will pattern match on the argument. If the argument is a user_id then the first instance of find_user/1 would be called if it’s passed a user_name the second one would be called.

I realize this sounds overly confusing, but pattern matching throughout Elixir opens a world of possibilities. Control flow is often simplified because one can disqualify all kinds of data before even passing it into the function. This saves the function work (often in the form of a complex control flow) qualifying what should be done with the data making for shorter functions and a more concise codebase.

Elixir is also blazing fast for web development, huge test suites run in a fraction of the time of much smaller Rspecs and live reloading out of the box for Phoenix projects had spoiled me to the point where I’m going to add reloading gems to my Rails projects.