While on a flight, I discovered something really fun about Elixir. If you talk to me about Elixir for 5 minutes, you'll find that I love the pipe operator in Elixir. It's a pleasant way to avoid the classical function nesting hell that other languages suffer from.
Let's look at an example from a project I'm working on. The code below takes the
conn object from
Plug.Conn and tests that the request is a true Twilio request. Here is the code using nested functions and my first pass at using pipes.
### # Nested Functions ### signature = List.first(get_req_header(conn, "x-twilio-signature")) is_valid = Validator.validate(url_from_conn(conn), conn.params, signature) if is_valid do conn else halt(send_resp(conn, 401, "Not authorized")) end ### # Piped Functions ### signature = conn |> get_req_header("x-twilio-signature") |> List.first if conn |> url_from_conn |> Validator.validate(conn.params, signature) do conn else conn |> send_resp(401, "Not authorized") end
With pipes, the response from each command in the call list gets passed as the first argument of the next. You can see that the piped functions style is much easier to read through than the function nesting, because we can read left to right, top to bottom; unlike the nested functions which read inside out.
Now for some fun
What makes Elixir fun to me is that everything is essentially a function, even
if statements. That means that I can take my code one step further:
signature = ... conn |> url_from_conn |> Validator.validate(conn.params, signature) |> if(do: conn, else: conn |> send_resp(401, "Not authorized") |> halt)
Elixir is a beautiful language that exposes programmers to thinking differently about how to approach the firm constructs that other languages setup. The ideas of functional programming sound strict at first, but as I dive deeper and deeper into this world, the Elixir language feels more fluid than any language that I've used in the past.