1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
//
// zug: transducers for C++
// Copyright (C) 2019 Juan Pedro Bolivar Puente
//
// This software is distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
//
#include <zug/compose.hpp>
#include <catch2/catch.hpp>
#include <array>
#include <functional>
#include <type_traits>
using namespace zug;
auto add_one = [](int x) { return x + 1; };
auto mult_five = [](int x) { return x * 5; };
auto fst = [](auto&& x) { return x[0]; };
auto divide = [](int x, int y) { return x / y; };
TEST_CASE("comp: call composed functions returns output of composition")
{
auto result = comp(add_one, add_one, add_one)(5);
CHECK(result == 8);
}
TEST_CASE("comp: execution order is from right to left function")
{
SECTION("add_one(mult_five(x))")
{
auto result = comp(add_one, mult_five)(10);
CHECK(result == 51);
}
SECTION("mult_five(add_one(x))")
{
auto result = comp(mult_five, add_one)(10);
CHECK(result == 55);
}
}
TEST_CASE("comp: supports transformation between input and output type")
{
static_assert(
std::is_same<
std::result_of_t<decltype(comp(add_one, fst))(std::array<int, 4>)>,
int>::value,
"comp should support transformation from array to int");
auto result = comp(add_one, fst)(std::array<int, 4>{{1, 2, 3, 4}});
CHECK(result == 2);
}
TEST_CASE("comp: supports multiple input arguments")
{
auto result = comp(add_one, divide)(10, 2);
CHECK(result == 6);
}
TEST_CASE("comp: supports single function with multiple args")
{
auto result = comp(divide)(10, 2);
CHECK(result == 5);
}
TEST_CASE("comp: comp a comp")
{
static_assert(
std::is_same<
decltype(comp(comp(add_one, add_one), divide)),
composed<decltype(add_one), decltype(add_one), decltype(divide)>>::
value,
"comping a comp produces a flattened composed");
auto result = comp(comp(add_one, add_one), divide)(12, 4);
CHECK(result == 5);
}
TEST_CASE("comp: comp two comps")
{
static_assert(
std::is_same<decltype(comp(comp(add_one), comp(add_one))),
composed<decltype(add_one), decltype(add_one)>>::value,
"comping two comps produces a flattened composed");
auto result = comp(comp(add_one), comp(add_one))(10);
CHECK(result == 12);
}
TEST_CASE("comp: comp an lvalue comp")
{
auto comped = comp(add_one);
auto result = comp(comped, comp(add_one))(10);
CHECK(result == 12);
}
TEST_CASE("comp: comp a const lvalue comp")
{
const auto comped = comp(add_one);
auto result = comp(comped, comped)(10);
CHECK(result == 12);
}
auto c_add_one = comp([](int x) { return x + 1; });
auto c_mult_five = comp([](int x) { return x * 5; });
TEST_CASE("operator|: call composed functions returns output of composition")
{
auto result = (c_add_one | c_add_one)(10);
CHECK(result == 12);
}
TEST_CASE("operator|: execution order is from right to left function")
{
SECTION("add_one(mult_five(x))")
{
auto result = (c_add_one | c_mult_five)(10);
CHECK(result == 51);
}
SECTION("mult_five(add_one(x))")
{
auto result = (c_mult_five | c_add_one)(10);
CHECK(result == 55);
}
}
TEST_CASE("operator|: composable non-composable type")
{
auto composable = comp([](auto x) { return x + 1; });
auto non_composable = [](auto x) { return x + 1; };
SECTION("composable | non-composable")
{
auto result = (composable | non_composable)(10);
CHECK(result == 12);
}
SECTION("non-composable | composable")
{
auto result = (non_composable | composable)(10);
CHECK(result == 12);
}
}
|