Giter Site home page Giter Site logo

sztheory / pit Goto Github PK

View Code? Open in Web Editor NEW

This project forked from vic/pit

0.0 1.0 0.0 26 KB

Elixir macro for extracting or transforming values inside a pipe flow.

Home Page: https://hex.pm/packages/pit

License: Apache License 2.0

Elixir 100.00%

pit's Introduction

Down the pit

help maintain this lib

Installation

Available in Hex, the package can be installed as:

  1. Add pit to your list of dependencies in mix.exs:
```elixir
def deps do
  [{:pit, "~> 1.2.0"}]
end
```

Usage

The pit macro lets you pipe value transformations by pattern matching on data as it is passed down the pipe.

The syntax for transforming values is expression |> pit(value <- pattern).

By default if a value does not match the pattern, pit simply passes down the value it was given. You can however enforce the pattern to match by using pit! which will raise an error on mismatch. Or you can provide an else: option to pit to handle the mismatch yourself.

See the following examples:

Examples

iex> # Pipe a value if a tagged tuple matches
iex> import Pit
...> {:ok, "hello"}
...>   |> pit(ok: String.length)
5

iex> # does not pipe if tagged tuple does not match
iex> import Pit
...> {:error, "hello"}
...>   |> pit(ok: String.length)
{:error, "hello"}


iex> # pit! raises on tagged tuple mismatch
iex> import Pit
...> {:error, "hello"}
...>   |> pit!(ok: String.length, yes: String.length)
** (Pit.PipedValueMismatch) expected piped value to be a tagged tuple with one of keys `[:ok, :yes]` but got `{:error, "hello"}`


iex> # this example transforms an ok tuple
iex> import Pit
...> value = {:ok, 11}
...> value
...>   |> pit(n * 2 <- {:ok, n})
22


iex> # If the value does not match, no transformation is made.
iex> import Pit
...> value = {:ok, :hi}
...> value
...>   |> pit(n * 2 <- {:ok, n} when is_number(n))
{:ok, :hi}


iex> # You can force the pattern to match by using `pit!`
iex> import Pit
...> value = {:ok, :hi}
...> value
...>   |> pit!(n * 2 <- {:ok, n} when is_number(n))
** (Pit.PipedValueMismatch) expected piped value to match `{:ok, n} when is_number(n)` but got `{:ok, :hi}`


iex> # The following will ensure there are no errors on
iex> # the response and double the count value from data.
iex> import Pit
...> response = {:ok, %{data: %{"count" => 10}, errors: []}}
...> response
...>    |> pit!(data <- {:ok, %{errors: [], data: data}})
...>    |> pit(count * 2 <- %{"count" => count})
20


iex> # The pattern can be negated with `not` or `!`.
iex> # in this case raise if an error tuple is found.
iex> import Pit
...> response = {:cool, 22}
...> response
...>    |> pit!(not {:error, _})
...>    |> pit(n <- {_, n})
22


iex> # should raise when using `pit!`
iex> import Pit
...> response = {:error, :not_found}
...> response
...>    |> pit!(not {:error, _})
...>    |> pit(n <- {_, n})
** (Pit.PipedValueMismatch) did not expect piped value to match `{:error, _}` but got `{:error, :not_found}`


iex> # also, when a guard fails an error is raised
iex> import Pit
...> response = {:ok, 22}
...> response
...>    |> pit!({:ok, n} when n > 30)
...>    |> pit(n <- {:ok, n})
** (Pit.PipedValueMismatch) expected piped value to match `{:ok, n} when n > 30` but got `{:ok, 22}`


iex> # If you use `pit!/1` at the final of your pipe, it will
iex> # extract the value that caused the mismatch.
iex> import Pit
...> value = {:error, 11}
...> value
...>   |> pit!({:ok, _})  # raises Pit.PipedValueMismatch
...>   |> Yeah.got_it     # never gets executed
...>   |> pit!            # rescue value from PipedValueMismatch
{:error, 11}


iex> # The `tag:` option lets you create a tagged tuple.
iex> # Tagging mismatch values can be useful for example to know which
iex> # pipe stage was the one that failed.
iex> import Pit
...> user = nil # ie. Repo.get_by User, email: "[email protected]"
...> user
...>   |> pit!(not nil, tag: :user) # raises Pit.PipedValueMismatch
...>   |> User.avatar_url           # never gets executed
...>   |> pit!                      # unwraps value from PipedValueMismatch
{:user, nil}


iex> # Tags also apply on matching patterns.
iex> import Pit
...> user = {:ok, 21} # ie. Universe.so_so_answer
...> user
...>   |> pit!(x * 2 <- {:ok, x}, tag: :answer)
{:answer, 42}


iex> # You can provide a default value in case of mismatch
iex> import Pit
...> response = {:error, :not_found}
...> response
...>    |> pit({:ok, _}, else: {:ok, :default})
...>    |> pit(n <- {:ok, n})
:default


iex> # Or you can pipe the mismatch value to other pipe using `else_pipe:` option
iex> # and get the value down a more interesting transformation flow.
iex> import Pit
...> response = {:ok, "hello"}
...> response
...>   |> pit({:ok, n} when is_integer(n),
...>        do: {:ok, :was_integer, n},
...>        else_pipe: pit(s <- {:ok, s} when is_binary(s)) |> String.length |> pit({:ok, :was_string, len} <- len))
...>   |> pit(x * 2 <- {:ok, _, x})
10


iex> # Both `do_pipe` and `else_pipe` if given the `:it` atom just pass the value down
iex> import Pit
...> {:error, 22} |> pit({:ok, _}, else_pipe: :it)
{:error, 22}

iex> import Pit
...> {:ok, 22} |> pit({:ok, _}, do_pipe: :it)
{:ok, 22}


iex> # The do form can take a block using bound variables.
iex> import Pit
...> {:ok, 22}
...> |> pit {:ok, n} do
...>    x = n / 11
...>    x * 2
...> end
4.0


iex> # You can omit parens even with negated pattern
iex> import Pit
...> {:failure, :nop}
...> |> pit not {:ok, _} do
...>   "Noup"
...> end
...> |> pit {:ok, _} do
...>   "Yeah"
...> end
"Noup"


iex> # You can of course provide both do/else
iex> import Pit
...> {:error, :nop}
...> |> pit {:ok, _} do
...>   "Yeah"
...> else
...>   "Noup"
...> end
"Noup"

pit's People

Contributors

vic avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.