Data massaging in pipes with anonymous functions

The pipe operator is great. So great, in fact, that sometimes you just want to keep that pipe juice flowing and feel bad about breaking it up just to massage data into the appropriate shape before continuing with a new pipe.

Anonymous functions can help out here. But you need to realize that each step in the pipe is a function call. Therefore, to use an anonymous function within a pipe, you have to call it with my_func.():

def to_email(full_name, domain) do
    full_name
    |> String.split()
    |> Enum.join(".")
    |> (&"#{&1}@#{domain}").()
    |> String.downcase()
 end

# iex> to_email("John Doe", "example.com")
# john.doe@example.com

On line 5, I simply wanted to create an email string without going through the fuss of writing a new function. Of course you can name the anonymous function, too:

def to_email(full_name, domain) do
    append_domain = &"#{&1}@#{domain}"

    full_name
    |> String.split()
    |> Enum.join(".")
    |> append_domain.()
    |> String.downcase()
end

As you’ve likely noticed, this technique is rife with potential for misuse and abuse: if you decide to use it, make sure your code’s readability doesn’t suffer! Otherwise, simply resort to the usual technique of grouping piped operations within larger functions (who have compatible output/input data shapes), and pipe those functions together.

This entry was posted in Elixir, Pattern snippets. Bookmark the permalink.