update README

This commit is contained in:
BlackMATov
2020-12-11 04:51:38 +07:00
parent de1232ebc7
commit 50fd7b7111
2 changed files with 195 additions and 72 deletions

124
README.md
View File

@@ -52,6 +52,8 @@ target_link_libraries(your_project_target kari.hpp)
### Basic currying
```cpp
using namespace kari_hpp;
auto foo = [](int v1, int v2, int v3) {
return v1 + v2 + v3;
};
@@ -68,13 +70,14 @@ std::cout << rr << std::endl;
### Partial application of curried functions
```cpp
auto foo = [](int v1, int v2, int v3, int v4) {
using namespace kari_hpp;
curry_t c0 = [](int v1, int v2, int v3, int v4) {
return v1 + v2 + v3 + v4;
};
auto c0 = curry(foo); // currying
auto c1 = c0(15, 20); // partial application of two arguments
auto rr = c1(2, 5); // partial application and call `foo(15,20,2,5)`
auto rr = c1(2, 5); // partial application and call `(15,20,2,5)`
// output: 42
std::cout << rr << std::endl;
@@ -83,17 +86,19 @@ std::cout << rr << std::endl;
### Calling nested curried functions
```cpp
auto boo = [](int v1, int v2) {
return v1 + v2;
using namespace kari_hpp;
curry_t boo = [](int a, int b) {
return a + b;
};
auto foo = [boo](int v1, int v2) {
return curry(boo, v1 + v2);
curry_t foo = [boo](int a, int b) {
return boo(a + b);
};
auto c0 = curry(foo)(38,3,1);
auto c1 = curry(foo)(38,3)(1);
auto c2 = curry(foo)(38)(3,1);
auto c0 = foo(38,3,1);
auto c1 = foo(38,3)(1);
auto c2 = foo(38)(3,1);
// output: 42,42,42
std::cout << c0 << "," << c1 << "," << c2 << std::endl;
@@ -102,19 +107,21 @@ std::cout << c0 << "," << c1 << "," << c2 << std::endl;
### Binding member functions and member objects
```cpp
struct Foo {
using namespace kari_hpp;
struct foo_t {
int v = 40;
int addV(int add) {
int add_v(int add) {
v += add;
return v;
}
} foo;
auto c0 = curry(&Foo::addV);
auto c1 = curry(&Foo::v);
auto c0 = curry(&foo_t::add_v);
auto c1 = curry(&foo_t::v);
auto r0 = c0(std::ref(foo))(2);
auto r1 = c1(foo);
auto r1 = c1(std::cref(foo));
// output: 42,42
std::cout << r0 << "," << r1 << std::endl;
@@ -125,13 +132,7 @@ std::cout << r0 << "," << r1 << std::endl;
```cpp
namespace kari_hpp {
template < typename F, typename... Args >
constexpr decltype(auto) curry(F&& f, Args&&... args) const;
template < typename F, typename... Args >
constexpr decltype(auto) curryV(F&& f, Args&&... args) const;
template < std::size_t N, typename F, typename... Args >
constexpr decltype(auto) curryN(F&& f, Args&&... args) const;
constexpr auto curry(F&& f, Args&&... args);
template < typename F >
struct is_curried;
@@ -139,10 +140,12 @@ namespace kari_hpp {
template < typename F >
inline constexpr bool is_curried_v = is_curried<F>::value;
template < std::size_t N, typename F, typename... Args >
struct curry_t {
template < typename F, typename... Args >
class curry_t {
constexpr curry_t(F f);
template < typename... As >
constexpr decltype(auto) operator()(As&&... as) const;
constexpr auto operator()(As&&... as) const;
};
}
```
@@ -155,43 +158,16 @@ Returns a curried function **`f`** or copy the function result with **`args`** a
---
### `kari_hpp::curryV(F&& f, Args&&... args)`
Allows carrying variadic functions.
```cpp
auto c0 = curryV(std::printf, "%d + %d = %d");
auto c1 = c0(37, 5);
auto c2 = c1(42);
// force calling carried variadic function
c2(); // output: 37 + 5 = 42
```
---
### `kari_hpp::curryN(F&& f, Args&&... args)`
Allows carrying variadic functions for **`N`** arguments.
```cpp
char buffer[256] = {'\0'};
auto c = curryN<3>(std::snprintf, buffer, 256, "%d + %d = %d");
c(37, 5, 42);
std::cout << buffer << std::endl; // output: 37 + 5 = 42
```
---
### `kari_hpp::is_curried<F>, kari_hpp::is_curried_v<F>`
Checks whether F is a curried function type.
```cpp
auto l = [](int v1, int v2){
return v1 + v2;
using namespace kari_hpp;
constexpr curry_t c = [](int a, int b){
return a + b;
};
auto c = curry(l);
// output: is `l` curried? no
std::cout
@@ -213,13 +189,14 @@ std::cout
Calling operator of curried function for partial application or full application. Returns a new curried function with added new arguments or copy of the function result.
```cpp
int foo(int v1, int v2, int v3, int v4) {
return v1 + v2 + v3 + v4;
}
using namespace kari_hpp;
auto c0 = curry(foo); // currying
auto c1 = c0(15, 20); // partial application
auto rr = c2(2, 5); // function call - foo(15,20,2,5)
curry_t c0 = [](int a, int b, int c, int d) {
return a + b + c + d;
};
auto c1 = c0(15, 20); // partial application
auto rr = c2(2, 5); // function call - foo(15,20,2,5)
// output: 42
std::cout << rr << std::endl;
@@ -232,17 +209,17 @@ std::cout << rr << std::endl;
### Section of operators
```cpp
using namespace underscore;
std::vector<int> v{1,2,3,4};
using namespace kari_hpp::ext::underscore;
std::vector v{1, 2, 3, 4};
// result: 10
std::accumulate(v.begin(), v.end(), 0, _+_);
std::accumulate(v.begin(), v.end(), 0, _ + _);
// v = 2, 3, 6, 8
std::transform(v.begin(), v.end(), v.begin(), _*2);
// v = {2, 4, 6, 8}
std::transform(v.begin(), v.end(), v.begin(), _ * 2);
// v = -2,-3,-6,-8
std::transform(v.begin(), v.end(), v.begin(), -_);
// v = {-2, -4, -6, -8}
std::transform(v.begin(), v.end(), v.begin(), - _);
```
### Function composition
@@ -250,7 +227,8 @@ std::transform(v.begin(), v.end(), v.begin(), -_);
#### Pipe operator
```cpp
using namespace underscore;
using namespace kari_hpp::ext;
using namespace kari_hpp::ext::underscore;
auto r0 = (_*2) | (_+2) | 4; // (4 * 2) + 2 = 10
auto r1 = 4 | (_*2) | (_+2); // (4 * 2 + 2) = 10
@@ -262,7 +240,8 @@ std::cout << r0, << "," << r1 << std::endl;
#### Compose operator
```cpp
using namespace underscore;
using namespace kari_hpp::ext;
using namespace kari_hpp::ext::underscore;
auto r0 = (_*2) * (_+2) * 4; // (4 + 2) * 2 = 12
auto r1 = 4 * (_*2) * (_+2); // (4 * 2 + 2) = 10
@@ -274,7 +253,8 @@ std::cout << r0, << "," << r1 << std::endl;
### Point-free style for Haskell maniacs
```cpp
using namespace underscore;
using namespace kari_hpp::ext;
using namespace kari_hpp::ext::underscore;
// (. (+2)) (*2) $ 10 == 24 // haskell analog
auto r0 = (_*(_+2))(_*2) * 10;

143
untests/kari_examples.cpp Normal file
View File

@@ -0,0 +1,143 @@
/*******************************************************************************
* This file is part of the "https://github.com/BlackMATov/kari.hpp"
* For conditions of distribution and use, see copyright notice in LICENSE.md
* Copyright (C) 2017-2020, by Matvey Cherevko (blackmatov@gmail.com)
******************************************************************************/
#include <kari.hpp/kari.hpp>
#include "doctest/doctest.hpp"
#include <algorithm>
#include <numeric>
#include <vector>
TEST_CASE("kari_examples") {
SUBCASE("Basic currying") {
using namespace kari_hpp;
auto foo = [](int a, int b, int c){
return a + b + c;
};
auto c0 = curry(foo); // currying of `foo` function
auto c1 = c0(10); // apply to first argument
auto c2 = c1(20); // apply to second argument
auto rr = c2(12); // apply to third argument and call the `foo` function
REQUIRE(rr == 42);
}
SUBCASE("Partial application") {
using namespace kari_hpp;
curry_t c0 = [](int v1, int v2, int v3, int v4) {
return v1 + v2 + v3 + v4;
};
auto c1 = c0(15, 20); // partial application of two arguments
auto rr = c1(2, 5); // partial application and call `(15,20,2,5)`
REQUIRE(rr == 42);
}
SUBCASE("Calling nested curried functions") {
using namespace kari_hpp;
curry_t boo = [](int a, int b) {
return a + b;
};
curry_t foo = [boo](int a, int b) {
return boo(a + b);
};
auto c0 = foo(38,3,1);
auto c1 = foo(38,3)(1);
auto c2 = foo(38)(3,1);
REQUIRE(c0 == 42);
REQUIRE(c1 == 42);
REQUIRE(c2 == 42);
}
SUBCASE("Binding member functions and member objects") {
using namespace kari_hpp;
struct foo_t {
int v = 40;
int add_v(int add) {
v += add;
return v;
}
} foo;
auto c0 = curry(&foo_t::add_v);
auto c1 = curry(&foo_t::v);
auto r0 = c0(std::ref(foo))(2);
auto r1 = c1(std::cref(foo));
REQUIRE(r0 == 42);
REQUIRE(r1 == 42);
}
SUBCASE("API/is_curried") {
using namespace kari_hpp;
constexpr curry_t c = [](int a, int b){
return a + b;
};
STATIC_REQUIRE(is_curried_v<decltype(c)>);
STATIC_REQUIRE(is_curried<decltype(c)>::value);
}
SUBCASE("Section of operators") {
using namespace kari_hpp::ext::underscore;
std::vector v{1, 2, 3, 4};
REQUIRE(std::accumulate(v.begin(), v.end(), 0, _ + _) == 10);
std::transform(v.begin(), v.end(), v.begin(), _ * 2);
REQUIRE(v == std::vector{2, 4, 6, 8});
std::transform(v.begin(), v.end(), v.begin(), - _);
REQUIRE(v == std::vector{-2, -4, -6, -8});
}
SUBCASE("Pipe operator") {
using namespace kari_hpp::ext;
using namespace kari_hpp::ext::underscore;
constexpr auto r0 = (_*2) | (_+2) | 4; // (4 * 2) + 2 = 10
constexpr auto r1 = 4 | (_*2) | (_+2); // (4 * 2 + 2) = 10
STATIC_REQUIRE(r0 == 10);
STATIC_REQUIRE(r1 == 10);
}
SUBCASE("Compose operator") {
using namespace kari_hpp::ext;
using namespace kari_hpp::ext::underscore;
constexpr auto r0 = (_*2) * (_+2) * 4; // (4 + 2) * 2 = 12
constexpr auto r1 = 4 * (_*2) * (_+2); // (4 * 2 + 2) = 10
STATIC_REQUIRE(r0 == 12);
STATIC_REQUIRE(r1 == 10);
}
SUBCASE("Point-free style") {
using namespace kari_hpp::ext;
using namespace kari_hpp::ext::underscore;
// (. (+2)) (*2) $ 10 == 24 // haskell analog
constexpr auto r0 = (_*(_+2))(_*2) * 10;
// ((+2) .) (*2) $ 10 == 22 // haskell analog
constexpr auto r1 = ((_+2)*_)(_*2) * 10;
STATIC_REQUIRE(r0 == 24);
STATIC_REQUIRE(r1 == 22);
}
}