Last active
September 23, 2017 09:32
-
-
Save mrange/d07a7fc9912487c17a104ad954c41264 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "stdafx.h" | |
#include <algorithm> | |
#include <cstdlib> | |
#include <cstdio> | |
#include <iostream> | |
#include <memory> | |
#include <string> | |
#include <type_traits> | |
#include <utility> | |
#include <vector> | |
#define CT__FWD(v) std::forward<decltype(v)> (v) | |
namespace transducer2 | |
{ | |
// Transducer: Context -> ('S -> 'S) -> ('S -> 'TIn -> 'S) -> ('S -> 'S)*('S -> 'TIn -> 'S) | |
namespace details | |
{ | |
template<typename TFolder> | |
struct folder_traits; | |
template<typename TStateRet, typename TStateArg, typename TValueArg> | |
struct folder_traits<TStateRet (*) (TStateArg, TValueArg)> | |
{ | |
using state_return_type = TStateRet ; | |
using state_arg_type = TStateRet ; | |
using value_arg_type = TValueArg ; | |
using decayed_value_type = std::decay_t<value_arg_type>; | |
}; | |
template<typename TBase, typename TStateRet, typename TStateArg, typename TValueArg> | |
struct folder_traits<TStateRet (TBase::*) (TStateArg, TValueArg)> | |
{ | |
using state_return_type = TStateRet ; | |
using state_arg_type = TStateRet ; | |
using value_arg_type = TValueArg ; | |
using decayed_value_type = std::decay_t<value_arg_type>; | |
}; | |
} | |
struct unit_t | |
{ | |
}; | |
constexpr auto unit = unit_t (); | |
struct context | |
{ | |
context() | |
: cont (true) | |
{ | |
} | |
bool cont; | |
}; | |
template<typename TCompleter, typename TFolder> | |
struct builtup | |
{ | |
TCompleter completer ; | |
TFolder folder ; | |
}; | |
template<typename TCompleter, typename TFolder> | |
constexpr auto create_builtup (TCompleter && c, TFolder && f) | |
{ | |
return builtup<std::decay_t<TCompleter>, std::decay_t<TFolder>> | |
{ | |
CT__FWD (c) | |
, CT__FWD (f) | |
}; | |
} | |
template<typename THead> | |
constexpr auto compose (THead && head) | |
{ | |
return CT__FWD (head); | |
} | |
template<typename THead, typename ...TTail> | |
constexpr auto compose (THead && head, TTail && ...tail) | |
{ | |
return [head, tail...](context & ctx, auto && completer, auto && folder) mutable | |
{ | |
// TODO: forward tail | |
auto tbu = compose (tail...) (ctx, CT__FWD (completer), CT__FWD (folder)); | |
return head (ctx, CT__FWD (tbu.completer), CT__FWD (tbu.folder)); | |
}; | |
} | |
auto trace (std::string name) | |
{ | |
return[name = CT__FWD (name)](context & ctx, auto && completer, auto && folder) | |
{ | |
return create_builtup | |
( | |
CT__FWD (completer) | |
, [name, folder = CT__FWD (folder)](auto && s, auto && v) mutable | |
{ | |
std::cout << "transducer - " << name << " - " << v << std::endl; | |
return folder (CT__FWD (s), CT__FWD (v)); | |
} | |
); | |
}; | |
} | |
template<typename TFilter> | |
constexpr auto filtering (TFilter && f) | |
{ | |
return[f = CT__FWD (f)](context & ctx, auto && completer, auto && folder) | |
{ | |
return create_builtup | |
( | |
CT__FWD (completer) | |
, [f, folder = CT__FWD (folder)](auto && s, auto && v) mutable | |
{ | |
return f (v) ? folder(CT__FWD (s), CT__FWD (v)) : CT__FWD (s); | |
} | |
); | |
}; | |
} | |
template<typename TMap> | |
constexpr auto mapping (TMap && m) | |
{ | |
return[m = CT__FWD (m)](context & ctx, auto && completer, auto && folder) | |
{ | |
return create_builtup | |
( | |
CT__FWD (completer) | |
, [m, folder = CT__FWD (folder)](auto && s, auto && v) mutable | |
{ | |
return folder(CT__FWD (s), m(CT__FWD (v))); | |
} | |
); | |
}; | |
} | |
auto skipping (std::size_t n) | |
{ | |
return [n = CT__FWD (n)](context & ctx, auto && completer, auto && folder) | |
{ | |
return create_builtup | |
( | |
CT__FWD (completer) | |
, [&ctx, rem = n, folder = CT__FWD (folder)](auto && s, auto && v) mutable | |
{ | |
if (rem > 0) | |
{ | |
--rem; | |
return CT__FWD (s); | |
} | |
else | |
{ | |
return folder (CT__FWD (s), CT__FWD (v)); | |
} | |
} | |
); | |
}; | |
} | |
auto taking (std::size_t n) | |
{ | |
return [n = CT__FWD (n)](context & ctx, auto && completer, auto && folder) | |
{ | |
return create_builtup | |
( | |
CT__FWD (completer) | |
, [&ctx, rem = n, folder = CT__FWD (folder)](auto && s, auto && v) mutable | |
{ | |
if (rem > 0) | |
{ | |
--rem; | |
return folder (CT__FWD (s), CT__FWD (v)); | |
} | |
else | |
{ | |
ctx.cont = false; | |
return CT__FWD (s); | |
} | |
} | |
); | |
}; | |
} | |
template<typename TSelector> | |
auto sort_by (std::size_t reserve, TSelector && selector) | |
{ | |
return [reserve, selector = CT__FWD (selector)](context & ctx, auto && completer, auto && folder) | |
{ | |
using ft = details::folder_traits<decltype(folder)>; | |
auto vs_up = std::make_unique<std::vector<typename ft::decayed_value_type>>(); | |
vs_up->reserve (reserve); | |
auto vs_rp = vs_up.get (); | |
return create_builtup | |
( | |
[selector, vs_up = CT__FWD (vs_up), folder = CT__FWD (folder)] (auto && s) mutable | |
{ | |
std::sort ( | |
vs_up->begin () | |
, vs_up->end () | |
, [&selector] (auto && l, auto && r) { return selector (CT__FWD (l)) < selector (CT__FWD (r)); } | |
); | |
auto ss = CT__FWD (s); | |
for (auto && v : *vs_up) | |
{ | |
ss = folder (CT__FWD (ss), CT__FWD (v)); | |
} | |
return CT__FWD (ss); | |
} | |
, [vs_rp](auto && s, auto && v) mutable | |
{ | |
vs_rp->push_back (CT__FWD (v)); | |
return CT__FWD (s); | |
} | |
); | |
}; | |
} | |
namespace range | |
{ | |
template<typename TTransducer, typename TFolder, typename TState> | |
constexpr auto transduce (TTransducer && t, TFolder && f, TState && z, int b, int e) | |
{ | |
auto s = std::forward<TState> (z); | |
context ctx ; | |
auto tbu = t( | |
ctx | |
, [] (auto && s) { return CT__FWD (s); } | |
, std::forward<TFolder> (f) | |
); | |
for (auto i = b; i < e && ctx.cont; ++i) | |
{ | |
s = tbu.folder (CT__FWD (s), i); | |
} | |
return tbu.completer(s); | |
} | |
} | |
} | |
namespace transducer | |
{ | |
// Transducer: Context -> ('S -> 'S) -> ('S -> 'TIn -> 'S) -> ('S -> 'S)*('S -> 'TIn -> 'S) | |
template<typename THead> | |
constexpr auto compose (THead && head) | |
{ | |
return CT__FWD (head); | |
} | |
template<typename THead, typename ...TTail> | |
constexpr auto compose (THead && head, TTail && ...tail) | |
{ | |
return [head, tail...](auto && folder) | |
{ | |
return head (compose (tail...) (CT__FWD (folder))); | |
}; | |
} | |
template<typename TFilter> | |
constexpr auto filtering (TFilter && f) | |
{ | |
return [f = CT__FWD (f)](auto && folder) | |
{ | |
return [f, folder = CT__FWD (folder)] (auto && s, auto && v) | |
{ | |
return f(v) ? folder(CT__FWD (s), CT__FWD (v)) : CT__FWD (s); | |
}; | |
}; | |
} | |
template<typename TMap> | |
constexpr auto mapping (TMap && m) | |
{ | |
return [m = CT__FWD (m)](auto && folder) | |
{ | |
return [m, folder = CT__FWD (folder)](auto && s, auto && v) | |
{ | |
return folder(CT__FWD (s), m(CT__FWD (v))); | |
}; | |
}; | |
} | |
auto skipping (std::size_t n) | |
{ | |
return [n = CT__FWD (n)](auto && folder) | |
{ | |
return [rem = n, folder = CT__FWD (folder)](auto && s, auto && v) mutable | |
{ | |
if (rem > 0) | |
{ | |
--rem; | |
return CT__FWD (s); | |
} | |
else | |
{ | |
return folder (CT__FWD (s), CT__FWD (v)); | |
} | |
}; | |
}; | |
} | |
auto taking (std::size_t n) | |
{ | |
return [n = CT__FWD (n)](auto && folder) | |
{ | |
return [rem = n, folder = CT__FWD (folder)](auto && s, auto && v) mutable | |
{ | |
if (rem > 0) | |
{ | |
--rem; | |
return folder (CT__FWD (s), CT__FWD (v)); | |
} | |
else | |
{ | |
return CT__FWD (s); | |
} | |
}; | |
}; | |
} | |
namespace range | |
{ | |
template<typename TTransducer, typename TFolder, typename TState> | |
constexpr auto transduce (TTransducer && t, TFolder && f, TState && z, int b, int e) | |
{ | |
auto s = std::forward<TState> (z); | |
auto tf = t(std::forward<TFolder> (f)); | |
for (auto i = b; i < e; ++i) | |
{ | |
s = tf (CT__FWD (s), i); | |
} | |
return s; | |
} | |
} | |
} | |
constexpr auto sum = [](auto && s, auto && v) | |
{ | |
return CT__FWD (s) + CT__FWD (v); | |
}; | |
constexpr auto id = [](auto && v) | |
{ | |
return CT__FWD (v); | |
}; | |
constexpr auto negate = [](auto && v) | |
{ | |
return -CT__FWD (v); | |
}; | |
void f () | |
{ | |
using namespace transducer; | |
auto t = compose ( | |
skipping (2) | |
, taking (6) | |
, mapping ([](int i) { return static_cast<long long> (i + 1); }) | |
, filtering ([](long long i) { return (i & 1) == 0; }) | |
, mapping ([](long long i) { return i + 1; }) | |
); | |
std::printf ("Hello\n"); | |
auto s = range::transduce (t, sum, 0LL, 0, 10); | |
std::printf ("%lld\n", s); | |
} | |
void g () | |
{ | |
using namespace transducer2; | |
auto t = compose ( | |
trace ("input") | |
, skipping (2) | |
, taking (6) | |
, mapping ([](int i) { return i + 1; }) | |
, filtering ([](int i) { return (i & 1) == 0; }) | |
, mapping ([](int i) { return i + 1; }) | |
, sort_by (10, negate) | |
, trace ("output") | |
); | |
std::printf ("Hello\n"); | |
auto s = range::transduce (t, sum, 0, 0, 100); | |
std::printf ("%d\n", s); | |
} | |
int main () | |
{ | |
f (); | |
g (); | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment