I am beginning to use ramda, but have doubts about how to implement functions ramda.
This code is to mount a select object to do queries for sequelize.
See code:
#include "stdafx.h"
//#include "utilities.h"
#include <cstdlib>
#include <iostream>
#include <tuple>
//https://stackoverflow.com/questions/26902633/how-to-iterate-over-a-stdtuple-in-c-11
template<class F, class...Ts, std::size_t...Is>
void for_each_in_tuple(const std::tuple<Ts...> & tuple, F func, std::index_sequence<Is...>) {
using expander = int[];
(void)expander {
0, ((void)func(std::get<Is>(tuple)), 0)...
};
}
template<class F, class...Ts>
void for_each_in_tuple( std::tuple<Ts...> & tuple, F func) {
for_each_in_tuple(tuple, func, std::make_index_sequence<sizeof...(Ts)>());
}
// https://stackoverflow.com/questions/42255534 (Yakk)
namespace notstd {
template<class T> struct tag_t { constexpr tag_t() {}; using type = T; };
template<class T> constexpr tag_t<T> tag{};
template<class Tag> using type_t = typename Tag::type;
template<class...Ts, class F>
void for_each_type(F&& f) {
using discard = int[];
(void)discard {
0, (void(
f(tag<Ts>)
), 0)...
};
}
}
// A component
class icomponent {
public:
virtual std::string id() = 0;
virtual ~icomponent() = default;
virtual void init() = 0;
virtual void dispose() = 0;
void say() const {
std::cout << "say: " << typeid(*this).name() << " ANDNAME: " << /*id( ).c_str( )*/"???" << std::endl;
}
};
class component_base : public icomponent
{
public:
virtual ~component_base() = default;
virtual void init()
{
// ... init context
}
virtual void dispose()
{
// ...
}
// ... more
};
// Sample components
class component_a : public component_base {
public:
virtual std::string id() override { return "component a"; }
};
class component_b : public component_base {
public:
virtual std::string id() override { return "component b"; }
};
class component_c : public component_base {
public:
virtual std::string id() override { return "component c"; }
};
// Interface component manager
class iprocessing_component_manager {
public:
virtual ~iprocessing_component_manager() = default;
virtual void init() = 0;
virtual icomponent* prepare() = 0;
virtual void recycle(icomponent* p) = 0;
virtual void dispose() = 0;
};
// Implementation component manager
template<typename T>
class type_processing_component_manager
: public iprocessing_component_manager {
public:
virtual ~type_processing_component_manager() = default;
virtual T* prepare() override
{
// Default create T or fetch from a object pool, etc ...
return new T;
}
};
// Implementation virt. methods component mgr
template<typename ... Ts>
class tuple_processing_component_manager
: public type_processing_component_manager<Ts>... {
public:
virtual ~tuple_processing_component_manager() = default;
virtual void init() override
{
std::cout << "init: " << typeid(*this).name() << std::endl;
}
template<typename T>
T* prepare()
{
return type_processing_component_manager<T>::prepare();
}
virtual void recycle(icomponent* p) override
{
// Delete pointer or return to an object pool, etc
delete p;
}
virtual void dispose() override
{
}
};
// The controller
template <typename... Ts>
class controller {
std::tuple< Ts...> tups;
public:
controller()
{
}
~controller() = default;
// Do some initialization
// https://stackoverflow.com/questions/16387354/template-tuple-calling-a-function-on-each-element
void init()
{
for_each_in_tuple(tups, [](auto &x) { x.say(); });
// m_component_manager->init();
}
// Process components
void process()
{
// A simple loop over components.
//but this does not get the stored objects!
//notstd::for_each_type<Ts...>([&](auto tag) {
// using component_t = notstd::type_t<decltype(tag)>;
}
// ... more stuff
};
int main(int argc, char** argv)
{
controller<component_a, component_c> c;
c.init();
c.process();
return 0;
}
Or see demo on link
答案 0 :(得分:1)
我有点犹豫,只是简单地回应一个已翻译的代码块,我的学习建议将是尝试用Ramda的那些逐一替换你已经拥有的功能。
除了犹豫之外,下面提供了一个示例,说明了使用Ramda的各种函数时代码的外观。
// The existing check for `!!string.length` allows for potential issues with
// arrays being passed in and incorrectly validating, so this will ensure the
// value is indeed a string before checking its length
const stringRequired = R.both(R.is(String), R.complement(R.isEmpty))
// `addFilter` produces a function that takes an object and uses the provided
// function to validate the value associated with the provided key if it exists
// otherwise using the provided `initial` value. If valid, an object containing
// the key and value will be returned, otherwise an empty object is returned.
const addFilter = (validate, initial, key) =>
R.pipe(
R.propOr(initial, key),
R.ifElse(validate, R.objOf(key), R.always({}))
)
// `selector` takes an object and passes it to each function generated by
// calling `addFilter`, merging the resulting objects together.
const selector = (q = {}) =>
R.converge(R.merge, [
addFilter(stringRequired, '', 'name'),
addFilter(Number.isInteger, 10, 'limit')
])(q)
console.log(selector())
console.log(selector({ name: 'David Costa' }))
console.log(selector({ limit: 50 }))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
答案 1 :(得分:1)
我认为你需要考虑为什么你想把它转换成Ramda (免责声明:我是Ramda的作者)Ramda是一个图书馆,一个工具包。在它有助于清理代码或者更容易理解问题及其解决方案时使用它。如果没有,请不要使用它。
那就是说,我使用Ramda重构了它:
我只是试着重构一下。最后,我将所有辅助函数替换为一个辅助函数,其中包含['limit', 10, numberRequired]
等条件列表,以创建与selector
等效的函数。
我确实沿途使用了一些Ramda函数,但是唯一提供实质性帮助的函数是assoc
,它创建了一个旧对象以及一个键和值。例如,使用compose(Boolean, length)
比const stringRequired = string => !!string.length
更清晰,但这并不是一个很大的区别。
在我看来,重要的变化是makeSelector
函数,这使得创建selector
函数更具说明性。这有点难看,如果我从头开始,我可能会以不同的方式编写它,但我在一系列步骤中完成了这一步,内联你的辅助函数,直到我有一个相同行为的相当短的函数。
// rules
const stringRequired = R.compose(Boolean, R.length)
const numberRequired = number => Number.isInteger(number)
// utils
const makeSelector = (conditions) => (query = {}) => R.reduce(
(select, [key, initial, validate]) => {
const value = key in select && validate(select[key]) ? select[key] : initial;
return validate(value) ? R.assoc(key, value, select) : select
},
query,
conditions
)
// main
const selector = makeSelector([
['limit', 10, numberRequired],
['name', '', stringRequired]
])
console.log(selector());
console.log(selector({ name: 'David Costa' }));
console.log(selector({ limit: 50 }));
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>