mirror of
https://github.com/BlackMATov/kari.hpp.git
synced 2025-12-13 04:56:49 +07:00
145 lines
3.9 KiB
C++
145 lines
3.9 KiB
C++
/*******************************************************************************
|
|
* 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-2023, by Matvey Cherevko (blackmatov@gmail.com)
|
|
******************************************************************************/
|
|
|
|
#include "kari_tests.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 auto l = [](int a, int b){
|
|
return a + b;
|
|
};
|
|
|
|
constexpr curry_t c = l;
|
|
|
|
STATIC_CHECK(is_curried_v<decltype(c)>);
|
|
STATIC_CHECK(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_CHECK(r0 == 10);
|
|
STATIC_CHECK(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_CHECK(r0 == 12);
|
|
STATIC_CHECK(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_CHECK(r0 == 24);
|
|
STATIC_CHECK(r1 == 22);
|
|
}
|
|
}
|