Skip to content

Instantly share code, notes, and snippets.

@mrange
Last active September 23, 2017 09:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrange/d07a7fc9912487c17a104ad954c41264 to your computer and use it in GitHub Desktop.
Save mrange/d07a7fc9912487c17a104ad954c41264 to your computer and use it in GitHub Desktop.
#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