README.md

# Guardsafe

[![Build Status](https://travis-ci.org/DevL/guardsafe.svg?branch=master)](https://travis-ci.org/DevL/guardsafe)
[![Inline docs](http://inch-ci.org/github/DevL/guardsafe.svg?branch=master)](http://inch-ci.org/github/DevL/guardsafe)
[![Hex.pm](https://img.shields.io/hexpm/v/guardsafe.svg)](https://hex.pm/packages/guardsafe)
[![Documentation](https://img.shields.io/badge/Documentation-online-c800c8.svg)](http://hexdocs.pm/guardsafe)

Macros expanding into code that can be safely used in guard clauses.

## Usage

Update your `mix.exs` file and run `mix deps.get`.
```elixir
defp deps do
  [{:guardsafe, "~> 0.5.0"}]
end
```

Import all the macros...
```elixir
defmodule MyModule do
  import Guardsafe
```

...or just the ones you need.
```elixir
defmodule MyOtherModule do
  import Guardsafe, only: [divisible_by?: 2, integer?: 1]
```

Now go forth and make your guard clauses more readable!
```elixir
def leap_year?(year) when not integer?(year), do: raise "That's not a proper year!"
def leap_year?(year) when divisible_by?(year, 400), do: true
def leap_year?(year) when divisible_by?(year, 100), do: false
def leap_year?(year), do: divisible_by?(year, 4)
```

Documentation for each macro is of course available in `iex`.
```
iex(1)> h Guardsafe.divisible_by?

                    defmacro divisible_by?(number, divisor)

Expands divisible_by?(number, divisor) into rem(number, divisor) == 0
```

## Available macros

**NB:** If a macro is translated into a function residing in another module
than `Kernel` you need to require it before use, e.g. `require Integer`.

#### Macros for checking types
* `atom?/1` - translates into `Kernel.is_atom/1`
* `binary?/1` - translates into `Kernel.is_binary/1`
* `bitstring?/1` - translates into `Kernel.is_bitstring/1`
* `boolean?/1` - translates into `Kernel.is_boolean/1`
* `float?/1` - translates into `Kernel.is_float/1`
* `function?/1` - translates into `Kernel.is_function/1`
* `function?/2` - translates into `Kernel.is_function/2`
* `integer?/1` - translates into `Kernel.is_integer/1`
* `list?/1` - translates into `Kernel.is_list/1`
* `map?/1` - translates into `Kernel.is_map/1`
* `nil?/1` - translates into `Kernel.is_nil/1`
* `number?/1` - translates into `Kernel.is_number/1`
* `pid?/1` - translates into `Kernel.is_pid/1`
* `port?/1` - translates into `Kernel.is_port/1`
* `reference?/1` - translates into `Kernel.is_reference/1`
* `tuple?/1` - translates into `Kernel.is_tuple/1`

#### Macros for checking values
* `divisible_by?/2` - checks whether two integers are evenly divisible.
* `even?/1` - returns true for even integers.
* `odd?/1` - returns true for odd integers.
* `within?/3` - checks whether a value is in the range of the last two arguments.

#### Macros for dates and times
* `date?/1` - checks if the term is an Erlang-style date tuple.
* `datetime?/1` - checks if the term is an Erlang-style datetime tuple.
* `time?/1` - checks if the term is an Erlang-style time tuple.

_These can come in handy when working with a library such as [GoodTimes](https://github.com/DevL/good_times)._

### Why nil? and float? instead of is_nil and is_float

While the Elixir core team thinks that `nil?` compared to `is_nil` is [an inconcistency](https://groups.google.com/forum/#!topic/elixir-lang-core/FaKJstePFV0), others, especially Rubyists, might be more comfortable with the `nil?` notation. Honestly though, this is mostly intended as a display of how Elixir's metaprogramming capabilities can be used to shape the look and feel of the language itself.

## Online documentation

For more information, see [the full documentation](http://hexdocs.pm/guardsafe).

## Contributing

1. Fork this repository
2. Create your feature branch (`git checkout -b quis-custodiet-ipsos-custodes`)
3. Commit your changes (`git commit -am 'Guards! Guards!'`)
4. Push to the branch (`git push origin quis-custodiet-ipsos-custodes`)
5. Create a new Pull Request