bool_ext 0.6.2

A crate which defines and implements a complete set of `Option`/`Result`-style Boolean functional combinators on Rust's `bool` primitive type.
Documentation
# bool_ext
A crate which defines and implements a complete set of Boolean functional combinators.

## FAQ
### Aren't there already crates like this?
Yes, there are, notably Daniel Keep's [boolinator](https://crates.io/crates/boolinator), and 
Rust's [`then()` and `then_some()`](https://doc.rust-lang.org/std/primitive.bool.html#method.then
) methods.

`boolinator` is a great crate and serves as an inspiration for this crate, as do some other sources.
However, `boolinator`'s provided set of combinators is not as complete as one might wish for (and, 
relatively minor nit, nor are the combinator names as short as they could be.  `boolinator`'s
interface is also stable (i.e. >v1.0.0) so this would be disruptive to address.)  

In Rust's case, `std` is conservative by design, and will only very slowly move toward a complete set of combinators for `bool`.
 
My hope is that this crate can serve as a testing ground for both the naming and scope of
boolean combinators to help inform the Rust lang team's discussion and decisions with usage data
and feedback. 

### It's just a bool--why is the API surface so large?
Well, because `bool` is a very versatile data type!  For example, adding to a collection only if the
item in question is not already present is a common operation.  `Map` datatypes often give you
this behavior by the nature of their design.  Other containers such as `Vec`, do not.  So instead
of highly stateful, imperative code:
```rust
    // ...
    let mut found = false;
    for needle in haystack {
        if needle == item {
            found = true;
            break;
        }
    }    
    
    if !found {
        haystack.push(item);
    }
```
or imperative/declarative hybrid code:
```rust
    // ...
    if !haystack.contains(&item) {
        haystack.push(item)
    }
```
`bool_ext` enables the following highly expressive, highly cohesive, declarative code:
```rust
    // ...
    haystack.contains(&item)
            .or_do(|| haystack.push(item));
```

### Should I use this? / I'm not sure about method-chaining/functional combinators
You are not alone!  Debuggers have not yet caught up to fluent API design techniques and
debugging fluent interfaces can indeed be objectively more work.  On the other hand, proponents 
(such as me) will tell you that by elevating one's thinking from "micromanaging the CPU" to
expressing one's intent by "shaping the data", far fewer bugs will be written in the first place, 
and the resulting code will be both more expressive and more maintainable (once the maintaining 
party has sufficient experience with this style of coding).

`bool_ext` is implemented according to Bjarne Stroustrup's now classic definition of a zero
-overhead abstraction, where 1) you only pay for what you use and 2) you couldn't implement the
abstraction any better if you coded it yourself by hand.
 
Addressing 1), the `bool_ext` create is very small, takes no dependencies, and most importantly
, *any methods* defined within the crate that *you do not use* are stripped out by the compiler
and *are not a part of your resulting binary*.

Regarding 2), each method is `#[inline]`'d, adheres to the Single Responsibility Principle, 
minimizes register pressure from inlining and when fully optimized (typically in release mode) 
should compile down to exactly the same (or better) code that could be written by hand.

### What about negating a boolean?
Up until v0.4.0, `bool_ext` contained a `_false()` variant for almost every method.  Thanks to input
from [izik1](https://github.com/izik1), and a lot of consideration, I decided that readability 
didn't suffer when using `boolean_condition().not().ok()` as opposed to 
`boolean_condition().ok_false()` or `boolean_condition().or_ok()`.  I do find 
`(!boolean_condition()).ok()` is significantly less readable (because of the required parentheses 
and because the order of operations no longer proceeds exclusively left-to-right), but as izik1 
pointed out, `std::ops::Not` alleviates this.  Thank you, izik1! :)

## License
Licensed under either:

    * MIT license (see LICENSE-MIT file)
    * Apache License, Version 2.0 (see LICENSE-APACHE file)
at your option.

## Contributions
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the 
work by you shall be dual licensed as above, without any additional terms or conditions.