Lambda 组合 lambda
Lambda to compose lambdas
我尝试用 C++ 编写一个函数,它可以组成可变数量的 lambda。我第一次尝试的作品(尽管我怀疑它并不完美)
template <typename F, typename G> auto compose(F f, G g) {
return
[f, g](auto &&...xs) { return g(f(std::forward<decltype(xs)>(xs)...)); };
}
template <typename F, typename G, typename... Fs>
auto pipe(F f, G g, Fs... fs) {
if constexpr (sizeof...(fs) > 0) {
auto fg = compose(f, g);
return pipe(fg, fs...);
} else {
return compose(f, g);
}
}
int main() {
auto add_x = [](const auto &x) {
return [x](auto y) {
std::cout << "+" << x << std::endl;
return y + x;
};
};
auto to_str = [](const auto &s) {
std::cout << "to_str" << std::endl;
return std::string("String:") + std::to_string(s);
};
auto add_1 = add_x(1);
auto add_2 = add_x(2);
auto add_3 = add_x(3);
auto piped = pipe(add_1, add_2, add_3, to_str);
auto x = piped(3);
std::cout << x << std::endl;
}
但是,我想让 pipe
函数本身成为一个 lambda 函数。然而,这有点困难,因为据我了解,lambda 无法捕获自己。这简单地使我的模板函数“lambdafying”成为问题。有没有人有替代方法或想法如何使用 lambda 函数获得类似的结果?
您可以使用 y 组合器来生成递归 lambda。
template<class Fun>
class y_combinator_result {
Fun fun_;
public:
template<class T>
explicit y_combinator_result(T &&fun): fun_(std::forward<T>(fun)) {}
template<class ...Args>
decltype(auto) operator()(Args &&...args) {
return fun_(std::ref(*this), std::forward<Args>(args)...);
}
};
template<class Fun>
decltype(auto) y_combinator(Fun &&fun) {
return y_combinator_result<std::decay_t<Fun>>(std::forward<Fun>(fun));
}
template <typename F, typename G> auto compose(F f, G g) {
return
[f, g](auto &&...xs) { return g(f(std::forward<decltype(xs)>(xs)...)); };
}
auto pipe = y_combinator([](auto self, auto f, auto g, auto... fs){
if constexpr (sizeof...(fs) > 0) {
auto fg = compose(f, g);
return self(fg, fs...);
} else {
return compose(f, g);
}
});
我尝试用 C++ 编写一个函数,它可以组成可变数量的 lambda。我第一次尝试的作品(尽管我怀疑它并不完美)
template <typename F, typename G> auto compose(F f, G g) {
return
[f, g](auto &&...xs) { return g(f(std::forward<decltype(xs)>(xs)...)); };
}
template <typename F, typename G, typename... Fs>
auto pipe(F f, G g, Fs... fs) {
if constexpr (sizeof...(fs) > 0) {
auto fg = compose(f, g);
return pipe(fg, fs...);
} else {
return compose(f, g);
}
}
int main() {
auto add_x = [](const auto &x) {
return [x](auto y) {
std::cout << "+" << x << std::endl;
return y + x;
};
};
auto to_str = [](const auto &s) {
std::cout << "to_str" << std::endl;
return std::string("String:") + std::to_string(s);
};
auto add_1 = add_x(1);
auto add_2 = add_x(2);
auto add_3 = add_x(3);
auto piped = pipe(add_1, add_2, add_3, to_str);
auto x = piped(3);
std::cout << x << std::endl;
}
但是,我想让 pipe
函数本身成为一个 lambda 函数。然而,这有点困难,因为据我了解,lambda 无法捕获自己。这简单地使我的模板函数“lambdafying”成为问题。有没有人有替代方法或想法如何使用 lambda 函数获得类似的结果?
您可以使用 y 组合器来生成递归 lambda。
template<class Fun>
class y_combinator_result {
Fun fun_;
public:
template<class T>
explicit y_combinator_result(T &&fun): fun_(std::forward<T>(fun)) {}
template<class ...Args>
decltype(auto) operator()(Args &&...args) {
return fun_(std::ref(*this), std::forward<Args>(args)...);
}
};
template<class Fun>
decltype(auto) y_combinator(Fun &&fun) {
return y_combinator_result<std::decay_t<Fun>>(std::forward<Fun>(fun));
}
template <typename F, typename G> auto compose(F f, G g) {
return
[f, g](auto &&...xs) { return g(f(std::forward<decltype(xs)>(xs)...)); };
}
auto pipe = y_combinator([](auto self, auto f, auto g, auto... fs){
if constexpr (sizeof...(fs) > 0) {
auto fg = compose(f, g);
return self(fg, fs...);
} else {
return compose(f, g);
}
});