The library is pronounced "kee-pops". It is a utility library for working with the functional-programming-esque features of rust and tuples.
Have you ever found yourself writing rust code like this?
```rust
fn somefalliblefunction() -> Option
somefalliblefunction().map(|input| (input, double(input)));
somefalliblefunction().andthen(|input| someotherfalliblefunction(input).map(|result| (input, result)));
vec![1,2,3].into_iter().map(|input| (input, double(input))) ```
You: "Well, sometimes. This explicit input-to-result-tuple-passing can be a bit annoying, but it is managable :)"
Then what about this?
```rust
fn somefunctionwithmanyoutputs() -> (usize, usize, usize) { (0, 0, 0) }
fn somefalliblefunction() -> Option
somefalliblefunction().map(|(a,b,c)| (a, b, c, a + b + c)) ```
"Yeah, ok. I see your point, but I don't think it's too ba.."
... then what about this slightly more realistic example?!?
```rust pub struct Apple; pub struct Banana; pub struct Chocolate; pub struct AppleBananaChocolateCakeRecipe; pub struct AppleBananaChocolateCake;
fn trygatherfruits() -> Option<(Apple, Banana)> {
Some((Apple, Banana))
}
fn getsomechocolateandholdonto(apple: &Apple, banana: &Banana) -> Chocolate {
Chocolate
}
fn searchforrecipeinbookshelfwhilecarrying(
apple: &Apple,
banana: &Banana,
chocolate: &Chocolate
) -> Option
trygatherfruits() .map(|(apple, banana)| { let chocolate = getsomechocolateandholdonto(&apple, &banana); (apple, banana, chocolate) }) .andthen(|(apple, banana, chocolate)| { searchforrecipeinbookshelfwhilecarrying(&apple, &banana, &chocolate) .map(|recipe| (apple, banana, chocolate, recipe)) }) .map(|(apple, banana, chocolate, recipe)| bakecake(apple, banana, chocolate, &recipe)) ```
" ... "
As you can see, sometimes mapping can get a bit messy and verbose. But there is
a solution: We can trade in some of that explicit input passing against some
implicit input-under-the-hood-threading. With keepops
the example above would
look like this.
```rust
trygatherfruits() .keeptuplemap(|(apple, banana)| getsomechocolateandholdonto(apple, banana)) .keeptupleandthen(|(apple, banana, chocolate)| searchforrecipeinbookshelfwhilecarrying(apple, banana, chocolate)) .map(|(apple, banana, chocolate, recipe)| bakecake(apple, banana, chocolate, &recipe))
```
Much smoother, am I right?
"Well, but th..."
Shhhhhh, I know, I know. It's not perfect, but it reduces repetition and that's the whole point of it. You don't have to use it if you don't want to.