pattern_tap v0.4.0 PatternTap

The pipe operator |> is an awesome feature of Elixir.

But when your result cannot be directly input into the next function, you have to stop, pattern match out the value you want and start piping again!

It is a common pattern to return data like {:ok, result} or {:error, reason}. When you want to handle both cases, something like elixir-pipes may be a better use case for you. But otherwise, for simple destructuring of data and returning it in one line (or to just let it fail) you can use PatternTap!

Not fun way

defmodule Foo do
  def get_stuff(input) do
    {:ok, intermediate_result} = input
      |> Enum.map(&(to_string(&1)))
      |> Foo.HardWorker.work
    {:ok, result} = intermediate_result
      |> Enum.map(&(Foo.IntermediateResult.handle(&1)))
    result
  end
end

Anytime where the object you want requires pattern matching but you want to either return on one line or continue piping, you can use PatternTap!

def my_function do
  {:ok, result} = something |> something_else
  result
end

Pattern Tap

Heres the above example using PatternTap

defmodule Foo do
  use PatternTap

  def get_stuff(input) do
    input
      |> Enum.map(&(to_string(&1)))
      |> Foo.HardWorker.work
      |> tap({:ok, r1} ~> r1) # tap({:ok, r1}, r1) is also a supported format
      |> Enum.map(&(Foo.IntermediateResult.handle(&1)))
      |> tap({:ok, r2} ~> r2) # tap({:ok, r2}, r2) is also a supported format
  end
end

And the second example

# tap({:ok, result}, result) also supported
def my_function do
  something |> something_else |> tap({:ok, result} ~> result)
end

Link to this section Summary

Functions

tap/3 will not leak variable scope, and so any variables created within it are sure not to accidentally harm outside bindings by replacing them with values you didn’t intend to

Leaks a pipelined value into the surrounding context as a new variable

Use within pipes to pull out data inside and continue piping

Link to this section Functions

Link to this macro destruct(data, pattern, return_var) (macro)

tap/3 will not leak variable scope, and so any variables created within it are sure not to accidentally harm outside bindings by replacing them with values you didn’t intend to.

For that reason, it can only return one value, which means other variables in the binding will go unused (and warn you about it). destruct/3 will act as tap/3 however leak the variable scope outside, allowing you to return one value and then use another.

Example: (doc test does not like this for some reason, but it works I promise…)

use PatternTap
[1,2,3,4] |> destruct([a, b | c] ~> c) |> Enum.concat([a, b])
[3,4,1,2]
Link to this macro leak(data, var) (macro)

Leaks a pipelined value into the surrounding context as a new variable.

Examples:

iex> "hey" |> String.upcase |> leak(uppercase) |> String.to_atom
:HEY
iex> uppercase
"HEY"
iex> {:ok, "the result"} |> leak({:ok, result})
{:ok, "the result"}
iex> result
"the result"
Link to this macro tap(data, pattern, return_var) (macro)

Use within pipes to pull out data inside and continue piping.

Example:

iex> use PatternTap
iex> [1,2,3,4] |> tap([_a, _b | c] ~> c) |> inspect()
"[3, 4]"