Implement react::map(func, vector)
This commit is contained in:
parent
343cb394b5
commit
d2afa09adf
1 changed files with 66 additions and 1 deletions
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#include <psemek/react/value.hpp>
|
#include <psemek/react/value.hpp>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace psemek::react
|
namespace psemek::react
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
@ -11,7 +13,7 @@ namespace psemek::react
|
||||||
template <typename F, typename ... Args>
|
template <typename F, typename ... Args>
|
||||||
auto map_impl(F func, value<Args> ... args)
|
auto map_impl(F func, value<Args> ... args)
|
||||||
{
|
{
|
||||||
using R = decltype(func(std::declval<Args const &>()...));
|
using R = std::decay_t<decltype(func(std::declval<Args const &>()...))>;
|
||||||
|
|
||||||
auto node = std::make_shared<detail::node<R>>();
|
auto node = std::make_shared<detail::node<R>>();
|
||||||
auto weak_node = std::weak_ptr{node};
|
auto weak_node = std::weak_ptr{node};
|
||||||
|
|
@ -46,6 +48,57 @@ namespace psemek::react
|
||||||
return value<R>(detail::internal_tag{}, std::move(node));
|
return value<R>(detail::internal_tag{}, std::move(node));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename F, typename T>
|
||||||
|
auto map_impl(F func, std::vector<value<T>> args)
|
||||||
|
{
|
||||||
|
using R = std::decay_t<decltype(func(std::declval<std::vector<T>>()))>;
|
||||||
|
|
||||||
|
auto node = std::make_shared<detail::node<R>>();
|
||||||
|
auto weak_node = std::weak_ptr{node};
|
||||||
|
|
||||||
|
auto internal_subscriber = [weak_node]{
|
||||||
|
if (auto node = weak_node.lock())
|
||||||
|
{
|
||||||
|
node->cached_value = std::nullopt;
|
||||||
|
node->internal_signal();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto external_subscriber = [weak_node](auto const &){
|
||||||
|
if (auto node = weak_node.lock())
|
||||||
|
{
|
||||||
|
if (!node->cached_value)
|
||||||
|
node->external_signal(node->value());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<util::signal<void>::subscription_token> internal_tokens;
|
||||||
|
std::vector<typename util::signal<T>::subscription_token> external_tokens;
|
||||||
|
|
||||||
|
internal_tokens.reserve(args.size());
|
||||||
|
external_tokens.reserve(args.size());
|
||||||
|
|
||||||
|
for (auto const & arg : args)
|
||||||
|
{
|
||||||
|
internal_tokens.push_back(arg.subscribe(detail::internal_tag{}, internal_subscriber));
|
||||||
|
external_tokens.push_back(arg.subscribe(external_subscriber));
|
||||||
|
}
|
||||||
|
|
||||||
|
node->getter = [
|
||||||
|
func = std::move(func),
|
||||||
|
internal_tokens = std::move(internal_tokens),
|
||||||
|
external_tokens = std::move(external_tokens),
|
||||||
|
args = std::move(args)]() -> R {
|
||||||
|
std::vector<T> arg_values;
|
||||||
|
arg_values.reserve(args.size());
|
||||||
|
for (auto const & arg : args)
|
||||||
|
arg_values.push_back(*arg);
|
||||||
|
return func(std::move(arg_values));
|
||||||
|
};
|
||||||
|
|
||||||
|
return value<R>(detail::internal_tag{}, std::move(node));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename F, typename ... Args>
|
template <typename F, typename ... Args>
|
||||||
|
|
@ -54,4 +107,16 @@ namespace psemek::react
|
||||||
return detail::map_impl(std::move(func), make_value(std::forward<Args>(args))...);
|
return detail::map_impl(std::move(func), make_value(std::forward<Args>(args))...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename F, typename T>
|
||||||
|
auto map(F func, std::vector<value<T>> args)
|
||||||
|
{
|
||||||
|
return detail::map_impl(std::move(func), std::move(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
value<std::vector<T>> unpack(std::vector<value<T>> args)
|
||||||
|
{
|
||||||
|
return map([](std::vector<T> x) -> std::vector<T> { return x; }, std::move(args));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue