# Ok Jose

[![help maintain this lib](](

A tiny library for piping values on a given pattern like the erlang idiom `{:ok, _}` and `{:error, _}` tuples.

You can also define your own pattern-matched pipes besides `ok` and `error`.

Besides `ok_jose` I've made a couple more of related macro libraries
that might be related (or useful depending on your needs and taste):

- [happy]( from back before `with` landed elixir 1.2
- [pit]( a kind of pipeable `with`.

## Installation

  1. Add ok_jose to your list of dependencies in `mix.exs`:

  def deps do
    [{:ok_jose, "~> 2.1.0"}]

## Motivation

A lot of erlang libraries follow the convention of returning `{:ok, _}` and `{:error, _}` tuples to denote 
the success or failure of a computation. It's my opinion that more people should embrace this convention
on their code, and this library helps by making it easier to pipe values by unwrapping them from the
tagged tuples.

This library is my try at having a beautiful syntax for a *happy pipe*, that is, a pipe that expects `{:ok, _}`
tuples to be returned by each piped function.
If any piped function returns a non matched value, the remaining functions expecting an `{:ok, _}` value wont get executed.

So, for example, the following code

|> case do
  {:ok, content} ->
    content |> Poison.Parser.parse()
  {:error, _} = error -> error

can be written as:

{:ok, filename}
|> Poison.Parser.parse
|> ok

The main advantage of the macros defined by OkJose is that you dont need to learn new syntax
it's just plain old Elixir piping. It's also very easy to define your own, as they are just
case clauses.

## Usage

### `use OkJose`

Provides you with the following macros:

##### `ok/2`

Pipes values into functions as long as they match `{:ok, _}`

{:ok, v} |> f |> g |> ok

##### `ok!/2`

Pipes values into functions but if at any point a value
does not match `{:ok, _}` raises a match error.

##### `error/2` and `error!/2`

Work exactly as the previous examples, but for tuples tagged as `:error`.

### `use OkJose.Pipe`

#### `defpipe`

This module lets you define your own pipes, actually the
previous `ok` pipe is defined like the following. Any
value not matching is just piped as-is down the pipe.

defpipe ok do
  {:ok, value} -> value

However if the pipe name ends with an exclamation mark,
and no clause matches, an error will be raise just as with
any function not matching on its arguments.

defpipe ok! do
  {:ok, value} -> value

With these you can define a pipe for working on common values
like ecto models and changesets.

defpipe ok_or_valid do
  {:ok, value} -> value
  changeset = %{valid?: true}  -> changeset

This way you can pipe ok values or valid changesets like:

{:ok, %User{}}
|> cast(params, @required)
|> put_change(:name, "John")
|> Repo.insert
|> update_jwk_token
|> ok_or_valid

You can also define pipes that for values based on a predicate
instead of just a pattern match. For example, if you need to
call some function to determine if the value is safe to be
passed through the rest of your pipe.

The `OkJose.pipe_when` macro takes a block of patterns and
expects each to return a form like `{true, value}` or `{false, value}`
The first boolean value on the tuple tells if the payload
is to be passed down the pipe or if the pipe must suspend execution.

This way you can use negative matches, for example
the following pipe will only let safe pets to be given to functions:

The predicate `?`-ending form of `defpipe` is just sugar for `pipe_when`

@dangerous [Lion, Wolf, Cocodrile]

defpipe pet_safe? do
  pet = %{__struct__: mod} when not mod in @dangerous -> 
    {true, pet}
  anything ->
    {false, pet}

And you can use them by just adding to the end of the pipe

{:ok, pet}
|> take_out
|> go_to(:park)
|> play_with(:kids)
|> pet_safe?

## About ok

OkJose was born a while ago, back before we had Elixir 1.0, and before Elixir had its
own `with` form to deal with this kind of problems. There are a lot of other libraries
for dealing with tagged tuples and in general for monads in elixir. I'd recommend you
to checkout these in particular: 

- [`ok`]( 
  A growing library, also has a list of alternatives at their Readme.

- [`happy`](
  Work on OkJose leadme to creating happy and later [`happy_with`](
  They are just a bit less-pipeable than OkJose, and more on the spirit of Elixir's `with`
- [`pit`](
  A weird one, for transforming and matching data at every pipe step. 
  I dont know what I was thinking while doing it, but maybe it can be of use to someone.

## Is it any good?


Take a look at the tests for more code examples.

##### マクロス Makurosu

[[Elixir macros](,] The things I do for beautiful code
― George Martin, Game of Thrones