FnExpr

Creates immediately invoked function expressions specifically IIFE to be used with the pipe operator.

The motiviation for this library was from Dave Thomas’ short talk Put This in Your Pipe, which was awesome. However, I found that the additional boilerplate syntax to immediately-invoke the function also a little funky.

Here is a (contrived) example, using the pipe operator and anonymous functions directly

iex> :apples
  ...> |> (fn atom -> Atom.to_string(atom) <> "__post" end).()
  ...> |> (fn (str) -> String.to_atom("pre__" <> str) end).()
  :pre__apples__post

The same example can be represented with the & capture operator.

iex> :apples
  ...> |> (&(Atom.to_string(&1) <> "__post")).()
  ...> |> (&(String.to_atom("pre__" <> &1))).()
  :pre__apples__post

Neither look that great, so we are introducing a && capture-and-run operator, as well as capture macro which includes support for both capture expressions (&1 + 1), as well as anonymous functions (fn x -> x + 1 end).

That same example above, would look like

iex> :apples
  ...> |> FnExpr.&&(Atom.to_string(&1) <> "__post")
  ...> |> FnExpr.&&(String.to_atom("pre__" <> &1))
  :pre__apples__post

If you prefer, you can use FnExpr like the following:

  defmodule FnExpr.ExampleInvoke do
    use FnExpr

    def piece_count(board) do
      board
      |> Enum.reduce({0, 0}, fn(piece, {black, white}) ->
            case piece do
              :black -> {black+1, white}
              :white -> {black, white+1}
              _ -> {black, white}
            end
         end)
    end

    def total_pieces_on(board) do
      board
      |> piece_count
      |> invoke(fn {black, white} -> black + white end)
      |> invoke("Total pieces: \#{&1}")
    end

  end

And a sample output would look like:

iex> [nil, :black, nil, :black, :white, nil, :black]
  ...> |> FnExpr.ExampleInvoke.total_pieces_on
  "Total pieces: 4"

In the example above, we are using the invoke macro, it takes the preceeding output from the pipe, as well as a function expression (or a capture expression).

If you passs in a capture expression, then you only have &1 available (the output from the previous pipe). Or, if you wanted greated pattern mataching, you can us the fn function expression notation.

Here’s a full example showing how to use the && macro. Note that && is not directly supported in Elixir as a capture and immediately execute operator, so you will need to include the module name FnExpr.&&.

  defmodule FnExpr.ExampleAndAnd do
    require FnExpr

    def combine(atom) do
      atom
      |> FnExpr.&&(Atom.to_string(&1) <> "__post")
      |> FnExpr.&&(String.to_atom("pre__" <> &1))
    end

  end

Installation

@deps [
  fn_expr: "~> 0.2.1"
]

Documentation can be found at hexdocs.pm/fn_expr.

License

MIT License


Created: 2017-06-15