## Contributing to FunctionalPlus

The main intention of this library is to provide small composable and [referentially transparent](https://en.wikipedia.org/wiki/Referential_transparency) functions.


### New Issues

Feel free to open [issues](https://github.com/Dobiasd/FunctionalPlus/issues) for any kind of bugs, problems, feature requests, or questions.

A good bug report should include:

- A clear title
- A detailed description of the problem or error
- The expected behavior
- (If possible) a minimal example or steps to reproduce
- Information about used compiler and platform

If you have problems installing FunctionalPlus please let us know by opening an issue. This will help us optimize the setup experience.


### Open Issues

If you are looking for a way to contribute, have a look into the [open issues](https://github.com/Dobiasd/FunctionalPlus/issues). Especially the ones tagged with "help wanted" could be interesting to you.


### Pull requests

A good [PR](https://github.com/Dobiasd/FunctionalPlus/pulls) should include:

- A clear Description
- Test cases
- Informative commit message

Before starting to write code, please check the issues to see if there is already work in progress regarding your concern to avoid redundant work.

------------------------

### Details of the inner workings

Let's say you have an idea for a new useful function you would like to [add](https://github.com/Dobiasd/FunctionalPlus/pulls).
The small example of `without` can already show a lot of things.

```c++
// API search type: without : (a, [a]) -> [a]
// fwd bind count: 1
// without(0, [1, 0, 0, 5, 3, 0, 1]) == [1, 5, 3, 1]
template <typename Container,
    typename T = typename Container::value_type>
Container without(T elem, const Container& xs)
{
    return drop_if(is_equal_to(elem), xs);
}
```

The function resides in `./include/fplus/filter.hpp`, because, well, it is some kind of filter. ;)

The coding style (what is lower/upper case, spaced instead of tabs, etc.) becomes apparent by just looking at the current code. Lines should not exceed 80 characters.

Every public exposed function (so everything not in `namespace internal`) should have an `API search type`. So the `./api_search/compile_all_and_deploy.sh` can parse the type and show it on the [website](http://www.editgym.com/fplus-api-search/). It will be run by a website admin after merging your pull request

If it makes sense to have a partially curried version of your function in `namespace fwd` for forward application and composition (data parameter as the last one), you should specify a `fwd bind count`. If your functions type is `foo : (a, b, c) -> d` then `generate/auto_generate.py` will insert a derived function `fwd::foo : (a, b) -> (c -> d)` into `./include/fplus/fwd_instances.autogenerated_defines` 

The `make` step will automatically call `python ./generate/auto_generate.py`, which will update the `fwd_instances.autogenerated_defines` file, as well as the amalgamated library in `include_all_in_one/include/fplus/fplus.hpp`.

As the maintainer, I will run `cd api_search && ./compile_all_and_deploy.sh && cd ..` once your pull request has been merged, in order to update the doc at http://www.editgym.com/fplus-api-search/.


A few unit tests would also be nice. In our example they belong into `./test/filter_test.cpp`

```c++
TEST_CASE("filter_test - without")
{
    using namespace fplus;
    typedef std::vector<int> Ints;
    REQUIRE_EQ(without(1, Ints({1,2,3})), Ints({2,3}));
    REQUIRE_EQ(without(5, Ints({1,2,3})), Ints({1,2,3}));
    REQUIRE_EQ(without(5, Ints({})), Ints({}));
}
```

Try to also cover corner cases you can think of.

Please do not hesitate to create a PR even if you are not completely sure if you have followed these guidelines correctly. We will help you perfect your contribution before merging.
