Implementing and wrapping function composition in C++ for lazy evaluation - c++

Suppose I have a naive implementation of an applicative, which is a name I picked for sanity and not that I know anything about Applicative type class from other languages. Here goes the implementation:
#include <iostream>
#include <string>
template <typename T>
struct applicative {
template <typename Fn>
auto then(Fn f) const {
return applicative<decltype(f(data_))>{f(data_)};
}
template <typename Fn>
auto and_last(Fn f) const {
return f(data_);
}
T data_;
};
int main() {
applicative<std::string>{"hello world"}
.then([](std::string const& s) {return s.size() * 4; })
.then([](int k) {return k - 2; })
.and_last([](int k) { std::cout << k << "\n"; });
}
Now, this could be improved in many ways. Providing something like make_applicative for in-place construction, trying to eliminate redundant copies and moves if there are any etc. But from the time I saw our ability to compose functions in C++, I feel like something better is possible. Any compose implementation would work, so let's pick the one in this codereview.stackexchange question. With it, we can say things like
auto f1 = [](std::pair<double,double> p) {return p.first + p.second; };
auto f2 = [](double x) {return std::make_pair(x, x + 1.0); };
auto f3 = [](double x, double y) {return x*y; };
auto g = compose(f1, f2, f3);
std::cout << g(2.0, 3.0) << std::endl; //prints '13', evaluated as (2*3) + ((2*3)+1)
Pretty nice. Going back to my idea, I think this should make possible a rework of my applicative implementation in following way:
auto sf = applicative<std::string>{}
.then([](std::string const& s) {return s.size() * 4; })
.then([](int k) {return k - 2; });
std::cout << sf.eval_with("hello world"); << "\n";
As you can see, this is sort-of lazy evaluated and we only supply value when we need it, with eval_with. I've been thinking about how to implement this new version for one hour now and I have no idea where to store operations and composed functions, what to make of applicative template parameter like we have here with std::string and many more problems. How would one implement something like this? Is it trivial as I initially hoped to be or does it require a lot of code? I really want this because I feel like this would buy me a lot by preventing a lot of argument passing on long chain of functions.
Edit: I am working on it a little more and turns out compose implementation I linked is not what I actually had in mind since we are still performing all the function calls in the chain and still passing arguments around. But you can answer assuming any compose function would work and choice of a better compose implementation would be a performance optimization. What I had in mind was more like following, taken from my example
applicative<std::string>{"hello world"}
.then([](std::string const& s) {return s.size() * 4; })
.then([](int k) {return k - 2; })
.and_last([](int k) { std::cout << k << "\n"; });
Those then calls would result in a single function call equivalent to (s.size() * 4) - 2 which could be evaluated with eval_with.

Is that what you want?
#include <iostream>
#include <string>
struct id
{
template <typename T>
auto operator()(T t) const
{
return t;
}
};
template <typename T, typename Func = id>
struct applicative {
applicative(Func f = Func())
: _f(f)
{
}
template <typename Fn>
auto then(Fn f) const {
auto composition = [=](T val) { return f(_f(val)); };
return applicative<T, decltype(composition)>(composition);
}
auto eval_with(T t)
{
return _f(t);
}
Func _f;
};
int main() {
auto sf = applicative<std::string>{}
.then([](std::string const& s) {return s.size() * 4; })
.then([](int k) {return k - 2; });
std::cout << sf.eval_with("hello world") << "\n";
}
Disclaimer: I didn't bother about perfect forwarding, so everything is passed by value.

Related

c++ argmax of function(vector) [duplicate]

I'm a spoiled Python programmer who is used to calculating the argmax of a collection with respect to some function with
max(collection, key=function)
For example:
l = [1,43,10,17]
a = max(l, key=lambda x: -1 * abs(42 - x))
a then contains 43, the number closest to 42.
Is it possible to write a C++ function which takes any "iterable" and any function and returns the argmax like above? I guess this would involve template parameters, the auto keyword, and range-based iteration, but I was not able to piece it together.
Since #leemes solutions are too many. All are correct, except that none attempts to imitate the Python version in your example, Here is my attempt to imitate that:
Convenient generic argmax-function just like Python version:
template<typename Container, typename Fn>
auto max(Container const & c, Fn && key) -> decltype(*std::begin(c))
{
if ( std::begin(c) == std::end(c) )
throw std::invalid_argument("empty container is not allowed.");
typedef decltype(*std::begin(c)) V;
auto cmp = [&](V a, V b){ return key(a) < key(b); };
return *std::max_element(std::begin(c), std::end(c), cmp);
}
And use it as:
std::vector<int> l = {1,43,10,17};
auto a = max(l, [](int x) { return -1 * std::abs(42-x); };
int l[] = {1,43,10,17}; //works with array also!
auto a = max(l, [](int x) { return -1 * std::abs(42-x); };
Note: Unlike the other solution, this max() returns the element itself, not the iterator to the element!
Also note this solution would work for user-defined container also:
namespace test
{
template<size_t N>
struct intcollection
{
int _data[N];
int const * begin() const { return _data; }
int const * end() const { return _data + N; }
};
}
test::intcollection<4> c{{1,43,10,17}};
auto r = max(c, [](int x) { return -1 * std::abs(42-x); });
See the live demo.
This is a two-step process. Define a function key which should get mapped to the elements, i.e. which is applied before the operation which finds the maximum. Wrap things together in a lambda expression defining the comparison for finding the maximum.
auto key = [](int x){
return -abs(42 - x);
};
std::max_element(l.begin(), l.end(), [key](int a, int b){
return key(a) < key(b);
});
Here, we have to capture key which was defined outside the second lambda function. (We could also have defined it inside). You can also put this in one single lambda function. When the 42 should be parameterized from outside the lambda, capture this as a variable:
int x = 42;
std::max_element(l.begin(), l.end(), [x](int a, int b){
return -abs(x - a) < -abs(x - b);
});
Note that std::max_element returns an iterator. To access the value / a reference to it, prepend it with *:
int x = 42;
auto nearest = std::min_element(l.begin(), l.end(), [x](int a, int b){
return abs(x - a) < abs(x - b);
});
std::cout << "Nearest to " << x << ": " << *nearest << std::endl;
You can nicely wrap this in a generic find_nearest function:
template<typename Iter>
Iter find_nearest(Iter begin, Iter end,
const typename std::iterator_traits<Iter>::value_type & value)
{
typedef typename std::iterator_traits<Iter>::value_type T;
return std::min_element(begin, end, [&value](const T& a, const T& b){
return abs(value - a) < abs(value - b);
});
}
auto a = find_nearest(l.begin(), l.end(), 42);
std::cout << *a << std::endl;
Live demo find_nearest: http://ideone.com/g7dMYI
A higher-order function similar to the argmax function in your question might look like this:
template<typename Iter, typename Function>
Iter argmax(Iter begin, Iter end, Function f)
{
typedef typename std::iterator_traits<Iter>::value_type T;
return std::min_element(begin, end, [&f](const T& a, const T& b){
return f(a) < f(b);
});
}
You can invoke this with the following code, having exactly the lambda function from your question:
auto a = argmax(l.begin(), l.end(), [](int x) { return -1 * abs(42 - x); });
std::cout << *a << std::endl;
Live demo argmax: http://ideone.com/HxLMap
The only remaining difference now is that this argmax function uses an iterator-based interface, which corresponds to the design of the C++ standard algorithms (<algorithm>). It's always a good idea to adapt your own coding style to the tools you're using.
If you want a container-based interface which returns the value directly, Nawaz provided a nice solution which requires the decltype-feature to correctly specify the return type. I decided to keep my version this way, so people can see the both alternative interface designs.

Recursive lambda functions in C++11

I am new to C++11. I am writing the following recursive lambda function, but it doesn't compile.
sum.cpp
#include <iostream>
#include <functional>
auto term = [](int a)->int {
return a*a;
};
auto next = [](int a)->int {
return ++a;
};
auto sum = [term,next,&sum](int a, int b)mutable ->int {
if(a>b)
return 0;
else
return term(a) + sum(next(a),b);
};
int main(){
std::cout<<sum(1,10)<<std::endl;
return 0;
}
compilation error:
vimal#linux-718q:~/Study/09C++/c++0x/lambda> g++ -std=c++0x sum.cpp
sum.cpp: In lambda function:
sum.cpp:18:36: error: ‘((<lambda(int, int)>*)this)-><lambda(int, int)>::sum’ cannot be used as a function
gcc version
gcc version 4.5.0 20091231 (experimental) (GCC)
But if I change the declaration of sum() as below, it works:
std::function<int(int,int)> sum = [term,next,&sum](int a, int b)->int {
if(a>b)
return 0;
else
return term(a) + sum(next(a),b);
};
Could someone please throw light on this?
Think about the difference between the auto version and the fully specified type version. The auto keyword infers its type from whatever it's initialized with, but what you're initializing it with needs to know what its type is (in this case, the lambda closure needs to know the types it's capturing). Something of a chicken-and-egg problem.
On the other hand, a fully specified function object's type doesn't need to "know" anything about what is being assigned to it, and so the lambda's closure can likewise be fully informed about the types its capturing.
Consider this slight modification of your code and it may make more sense:
std::function<int(int,int)> sum;
sum = [term,next,&sum](int a, int b)->int {
if(a>b)
return 0;
else
return term(a) + sum(next(a),b);
};
Obviously, this wouldn't work with auto. Recursive lambda functions work perfectly well (at least they do in MSVC, where I have experience with them), it's just that they aren't really compatible with type inference.
The trick is to feed in the lambda implementation to itself as a parameter, not by capture.
const auto sum = [term,next](int a, int b) {
auto sum_impl=[term,next](int a,int b,auto& sum_ref) mutable {
if(a>b){
return 0;
}
return term(a) + sum_ref(next(a),b,sum_ref);
};
return sum_impl(a,b,sum_impl);
};
All problems in computer science can be solved by another level of indirection. I first found this easy trick at http://pedromelendez.com/blog/2015/07/16/recursive-lambdas-in-c14/
It does require C++14 while the question is on C++11, but perhaps interesting to most.
Going via std::function is also possible but can result in slower code. But not always. Have a look at the answers to std::function vs template
With C++14, it is now quite easy to make an efficient recursive lambda without having to incur the additional overhead of std::function, in just a few lines of code (with a small edit from the original to prevent the user from taking an accidental copy):
template <class F>
struct y_combinator {
F f; // the lambda will be stored here
// a forwarding operator():
template <class... Args>
decltype(auto) operator()(Args&&... args) const {
// we pass ourselves to f, then the arguments.
// [edit: Barry] pass in std::ref(*this) instead of *this
return f(std::ref(*this), std::forward<Args>(args)...);
}
};
// helper function that deduces the type of the lambda:
template <class F>
y_combinator<std::decay_t<F>> make_y_combinator(F&& f) {
return {std::forward<F>(f)};
}
with which your original sum attempt becomes:
auto sum = make_y_combinator([term,next](auto sum, int a, int b) {
if (a>b) {
return 0;
}
else {
return term(a) + sum(next(a),b);
}
});
I have another solution, but work only with stateless lambdas:
void f()
{
static int (*self)(int) = [](int i)->int { return i>0 ? self(i-1)*i : 1; };
std::cout<<self(10);
}
Trick here is that lambdas can access static variables and you can convert stateless ones to function pointer.
You can use it with standard lambdas:
void g()
{
int sum;
auto rec = [&sum](int i) -> int
{
static int (*inner)(int&, int) = [](int& _sum, int i)->int
{
_sum += i;
return i>0 ? inner(_sum, i-1)*i : 1;
};
return inner(sum, i);
};
}
Its work in GCC 4.7
You can make a lambda function call itself recursively. The only thing you need to do is to is to reference it through a function wrapper so that the compiler knows it's return and argument type (you can't capture a variable -- the lambda itself -- that hasn't been defined yet).
function<int (int)> f;
f = [&f](int x) {
if (x == 0) return 0;
return x + f(x-1);
};
printf("%d\n", f(10));
Be very careful not to run out of the scope of the wrapper f.
To make lambda recursive without using external classes and functions (like std::function or fixed-point combinator) one can use the following construction in C++14 (live example):
#include <utility>
#include <list>
#include <memory>
#include <iostream>
int main()
{
struct tree
{
int payload;
std::list< tree > children = {}; // std::list of incomplete type is allowed
};
std::size_t indent = 0;
// indication of result type here is essential
const auto print = [&] (const auto & self, const tree & node) -> void
{
std::cout << std::string(indent, ' ') << node.payload << '\n';
++indent;
for (const tree & t : node.children) {
self(self, t);
}
--indent;
};
print(print, {1, {{2, {{8}}}, {3, {{5, {{7}}}, {6}}}, {4}}});
}
prints:
1
2
8
3
5
7
6
4
Note, result type of lambda should be specified explicitly.
I ran a benchmark comparing a recursive function vs a recursive lambda function using the std::function<> capture method. With full optimizations enabled on clang version 4.1, the lambda version ran significantly slower.
#include <iostream>
#include <functional>
#include <chrono>
uint64_t sum1(int n) {
return (n <= 1) ? 1 : n + sum1(n - 1);
}
std::function<uint64_t(int)> sum2 = [&] (int n) {
return (n <= 1) ? 1 : n + sum2(n - 1);
};
auto const ITERATIONS = 10000;
auto const DEPTH = 100000;
template <class Func, class Input>
void benchmark(Func&& func, Input&& input) {
auto t1 = std::chrono::high_resolution_clock::now();
for (auto i = 0; i != ITERATIONS; ++i) {
func(input);
}
auto t2 = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(t2-t1).count();
std::cout << "Duration: " << duration << std::endl;
}
int main() {
benchmark(sum1, DEPTH);
benchmark(sum2, DEPTH);
}
Produces results:
Duration: 0 // regular function
Duration: 4027 // lambda function
(Note: I also confirmed with a version that took the inputs from cin, so as to eliminate compile time evaluation)
Clang also produces a compiler warning:
main.cc:10:29: warning: variable 'sum2' is uninitialized when used within its own initialization [-Wuninitialized]
Which is expected, and safe, but should be noted.
It's great to have a solution in our toolbelts, but I think the language will need a better way to handle this case if performance is to be comparable to current methods.
Note:
As a commenter pointed out, it seems latest version of VC++ has found a way to optimize this to the point of equal performance. Maybe we don't need a better way to handle this, after all (except for syntactic sugar).
Also, as some other SO posts have outlined in recent weeks, the performance of std::function<> itself may be the cause of slowdown vs calling function directly, at least when the lambda capture is too large to fit into some library-optimized space std::function uses for small-functors (I guess kinda like the various short string optimizations?).
This is a slightly simpler implementation of the fixpoint operator which makes it a little more obvious exactly what's going on.
#include <iostream>
#include <functional>
using namespace std;
template<typename T, typename... Args>
struct fixpoint
{
typedef function<T(Args...)> effective_type;
typedef function<T(const effective_type&, Args...)> function_type;
function_type f_nonr;
T operator()(Args... args) const
{
return f_nonr(*this, args...);
}
fixpoint(const function_type& p_f)
: f_nonr(p_f)
{
}
};
int main()
{
auto fib_nonr = [](const function<int(int)>& f, int n) -> int
{
return n < 2 ? n : f(n-1) + f(n-2);
};
auto fib = fixpoint<int,int>(fib_nonr);
for (int i = 0; i < 6; ++i)
{
cout << fib(i) << '\n';
}
}
C++ 14:
Here is a recursive anonymous stateless/no capture generic set of lambdas
that outputs all numbers from 1, 20
([](auto f, auto n, auto m) {
f(f, n, m);
})(
[](auto f, auto n, auto m) -> void
{
cout << typeid(n).name() << el;
cout << n << el;
if (n<m)
f(f, ++n, m);
},
1, 20);
If I understand correctly this is using the Y-combinator solution
And here is the sum(n, m) version
auto sum = [](auto n, auto m) {
return ([](auto f, auto n, auto m) {
int res = f(f, n, m);
return res;
})(
[](auto f, auto n, auto m) -> int
{
if (n > m)
return 0;
else {
int sum = n + f(f, n + 1, m);
return sum;
}
},
n, m); };
auto result = sum(1, 10); //result == 55
Here is the final answer for the OP. Anyway, Visual Studio 2010 does not support capturing global variables. And you do not need to capture them because global variable is accessable globally by define. The following answer uses local variable instead.
#include <functional>
#include <iostream>
template<typename T>
struct t2t
{
typedef T t;
};
template<typename R, typename V1, typename V2>
struct fixpoint
{
typedef std::function<R (V1, V2)> func_t;
typedef std::function<func_t (func_t)> tfunc_t;
typedef std::function<func_t (tfunc_t)> yfunc_t;
class loopfunc_t {
public:
func_t operator()(loopfunc_t v)const {
return func(v);
}
template<typename L>
loopfunc_t(const L &l):func(l){}
typedef V1 Parameter1_t;
typedef V2 Parameter2_t;
private:
std::function<func_t (loopfunc_t)> func;
};
static yfunc_t fix;
};
template<typename R, typename V1, typename V2>
typename fixpoint<R, V1, V2>::yfunc_t fixpoint<R, V1, V2>::fix = [](tfunc_t f) -> func_t {
return [f](fixpoint<R, V1, V2>::loopfunc_t x){ return f(x(x)); }
([f](fixpoint<R, V1, V2>::loopfunc_t x) -> fixpoint<R, V1, V2>::func_t{
auto &ff = f;
return [ff, x](t2t<decltype(x)>::t::Parameter1_t v1,
t2t<decltype(x)>::t::Parameter1_t v2){
return ff(x(x))(v1, v2);
};
});
};
int _tmain(int argc, _TCHAR* argv[])
{
auto term = [](int a)->int {
return a*a;
};
auto next = [](int a)->int {
return ++a;
};
auto sum = fixpoint<int, int, int>::fix(
[term,next](std::function<int (int, int)> sum1) -> std::function<int (int, int)>{
auto &term1 = term;
auto &next1 = next;
return [term1, next1, sum1](int a, int b)mutable ->int {
if(a>b)
return 0;
else
return term1(a) + sum1(next1(a),b);
};
});
std::cout<<sum(1,10)<<std::endl; //385
return 0;
}
You're trying to capture a variable (sum) you're in the middle of defining. That can't be good.
I don't think truely self-recursive C++0x lambdas are possible. You should be able to capture other lambdas, though.
This answer is inferior to Yankes' one, but still, here it goes:
using dp_type = void (*)();
using fp_type = void (*)(dp_type, unsigned, unsigned);
fp_type fp = [](dp_type dp, unsigned const a, unsigned const b) {
::std::cout << a << ::std::endl;
return reinterpret_cast<fp_type>(dp)(dp, b, a + b);
};
fp(reinterpret_cast<dp_type>(fp), 0, 1);
You need a fixed point combinator. See this.
or look at the following code:
//As decltype(variable)::member_name is invalid currently,
//the following template is a workaround.
//Usage: t2t<decltype(variable)>::t::member_name
template<typename T>
struct t2t
{
typedef T t;
};
template<typename R, typename V>
struct fixpoint
{
typedef std::function<R (V)> func_t;
typedef std::function<func_t (func_t)> tfunc_t;
typedef std::function<func_t (tfunc_t)> yfunc_t;
class loopfunc_t {
public:
func_t operator()(loopfunc_t v)const {
return func(v);
}
template<typename L>
loopfunc_t(const L &l):func(l){}
typedef V Parameter_t;
private:
std::function<func_t (loopfunc_t)> func;
};
static yfunc_t fix;
};
template<typename R, typename V>
typename fixpoint<R, V>::yfunc_t fixpoint<R, V>::fix =
[](fixpoint<R, V>::tfunc_t f) -> fixpoint<R, V>::func_t {
fixpoint<R, V>::loopfunc_t l = [f](fixpoint<R, V>::loopfunc_t x) ->
fixpoint<R, V>::func_t{
//f cannot be captured since it is not a local variable
//of this scope. We need a new reference to it.
auto &ff = f;
//We need struct t2t because template parameter
//V is not accessable in this level.
return [ff, x](t2t<decltype(x)>::t::Parameter_t v){
return ff(x(x))(v);
};
};
return l(l);
};
int _tmain(int argc, _TCHAR* argv[])
{
int v = 0;
std::function<int (int)> fac =
fixpoint<int, int>::fix([](std::function<int (int)> f)
-> std::function<int (int)>{
return [f](int i) -> int{
if(i==0) return 1;
else return i * f(i-1);
};
});
int i = fac(10);
std::cout << i; //3628800
return 0;
}

Very generic argmax function in C++ wanted

I'm a spoiled Python programmer who is used to calculating the argmax of a collection with respect to some function with
max(collection, key=function)
For example:
l = [1,43,10,17]
a = max(l, key=lambda x: -1 * abs(42 - x))
a then contains 43, the number closest to 42.
Is it possible to write a C++ function which takes any "iterable" and any function and returns the argmax like above? I guess this would involve template parameters, the auto keyword, and range-based iteration, but I was not able to piece it together.
Since #leemes solutions are too many. All are correct, except that none attempts to imitate the Python version in your example, Here is my attempt to imitate that:
Convenient generic argmax-function just like Python version:
template<typename Container, typename Fn>
auto max(Container const & c, Fn && key) -> decltype(*std::begin(c))
{
if ( std::begin(c) == std::end(c) )
throw std::invalid_argument("empty container is not allowed.");
typedef decltype(*std::begin(c)) V;
auto cmp = [&](V a, V b){ return key(a) < key(b); };
return *std::max_element(std::begin(c), std::end(c), cmp);
}
And use it as:
std::vector<int> l = {1,43,10,17};
auto a = max(l, [](int x) { return -1 * std::abs(42-x); };
int l[] = {1,43,10,17}; //works with array also!
auto a = max(l, [](int x) { return -1 * std::abs(42-x); };
Note: Unlike the other solution, this max() returns the element itself, not the iterator to the element!
Also note this solution would work for user-defined container also:
namespace test
{
template<size_t N>
struct intcollection
{
int _data[N];
int const * begin() const { return _data; }
int const * end() const { return _data + N; }
};
}
test::intcollection<4> c{{1,43,10,17}};
auto r = max(c, [](int x) { return -1 * std::abs(42-x); });
See the live demo.
This is a two-step process. Define a function key which should get mapped to the elements, i.e. which is applied before the operation which finds the maximum. Wrap things together in a lambda expression defining the comparison for finding the maximum.
auto key = [](int x){
return -abs(42 - x);
};
std::max_element(l.begin(), l.end(), [key](int a, int b){
return key(a) < key(b);
});
Here, we have to capture key which was defined outside the second lambda function. (We could also have defined it inside). You can also put this in one single lambda function. When the 42 should be parameterized from outside the lambda, capture this as a variable:
int x = 42;
std::max_element(l.begin(), l.end(), [x](int a, int b){
return -abs(x - a) < -abs(x - b);
});
Note that std::max_element returns an iterator. To access the value / a reference to it, prepend it with *:
int x = 42;
auto nearest = std::min_element(l.begin(), l.end(), [x](int a, int b){
return abs(x - a) < abs(x - b);
});
std::cout << "Nearest to " << x << ": " << *nearest << std::endl;
You can nicely wrap this in a generic find_nearest function:
template<typename Iter>
Iter find_nearest(Iter begin, Iter end,
const typename std::iterator_traits<Iter>::value_type & value)
{
typedef typename std::iterator_traits<Iter>::value_type T;
return std::min_element(begin, end, [&value](const T& a, const T& b){
return abs(value - a) < abs(value - b);
});
}
auto a = find_nearest(l.begin(), l.end(), 42);
std::cout << *a << std::endl;
Live demo find_nearest: http://ideone.com/g7dMYI
A higher-order function similar to the argmax function in your question might look like this:
template<typename Iter, typename Function>
Iter argmax(Iter begin, Iter end, Function f)
{
typedef typename std::iterator_traits<Iter>::value_type T;
return std::min_element(begin, end, [&f](const T& a, const T& b){
return f(a) < f(b);
});
}
You can invoke this with the following code, having exactly the lambda function from your question:
auto a = argmax(l.begin(), l.end(), [](int x) { return -1 * abs(42 - x); });
std::cout << *a << std::endl;
Live demo argmax: http://ideone.com/HxLMap
The only remaining difference now is that this argmax function uses an iterator-based interface, which corresponds to the design of the C++ standard algorithms (<algorithm>). It's always a good idea to adapt your own coding style to the tools you're using.
If you want a container-based interface which returns the value directly, Nawaz provided a nice solution which requires the decltype-feature to correctly specify the return type. I decided to keep my version this way, so people can see the both alternative interface designs.

How to apply a tuple of actions on tuple of numbers?

I have two tuples, one containing values and another tuple containing actions for these values.
Now I want to apply the corresponding action on each value, with as little code "overhead" as possible.
Something like the simplified example below.
#include <iostream>
#include <boost/hana.hpp>
namespace hana = boost::hana;
using namespace hana::literals;
struct ThinkPositive
{
void operator()(int &val) const
{
std::cout << "Think positive!\n";
val = std::abs(val);
}
};
struct Nice
{
void operator()(int &val) const
{
std::cout << val << " is nice!\n";
}
};
void numbers()
{
auto handlers = hana::make_tuple(Nice{}, ThinkPositive{});
auto nums = hana::make_tuple(5, -12);
auto handlers_and_nums = hana::zip(handlers, nums);
hana::for_each(handlers_and_nums, [](auto &handler_num) {
handler_num[0_c](handler_num[1_c]);
});
auto result = hana::transform(handlers_and_nums, [](const auto &handler_num) {
return handler_num[1_c];
});
hana::for_each(result, [](const auto num) {
std::cout << "got " << num << '\n';
});
}
int main()
{
numbers();
}
While the example above works it would be nicer to modify the contents of nums in place.
Is there a way to modify nums in place?
You could use zip_with, but it seems to be against its nature (it requires the function to actually return something, but your operators () return nothing:
auto special_compose = [](auto&& l, auto&& r){ l(r); return 0; };
hana::zip_with(special_compose, handlers, nums);
demo
If you can make your operators return something, you could go with lockstep:
hana::fuse(hana::fuse(hana::lockstep(hana::always(0)))(handlers))(nums);
demo
There should be something like lockstep defined without the outer f call, but I found nothing in the docs.
A little more standard solution (won't fit your requirement of as little code overhead as possible):
template<typename Fs, typename Params, size_t... is>
void apply_in_lockstep_impl(Fs&& fs, Params&& ps, std::index_sequence<is...>){
int x[] = { (fs[hana::integral_c<size_t,is>](ps[hana::integral_c<size_t,is>]),0)... };
}
template<typename Fs, typename Params>
void apply_in_lockstep(Fs&& fs, Params&& ps){
static_assert(hana::size(fs) == hana::size(ps), "");
apply_in_lockstep_impl(std::forward<Fs>(fs),
std::forward<Params>(ps),
std::make_index_sequence<decltype(hana::size(ps))::value>{});
}
but at the call site it is prettier:
apply_in_lockstep(handlers, nums);
demo
As was pointed in the comments another level of indirection can also help.
Here this would mean to transform the sequence into a sequence of pointer, via which the original values are modified.
auto nums_ptr = hana::transform(nums, [](auto &num) { return &num; });
auto handlers_and_nums = hana::zip(handlers, nums_ptr);
hana::for_each(handlers_and_nums, [](auto &handler_num) {
handler_num[0_c](*handler_num[1_c]);
});
demo
Another, more "traditional", way is to iterate over a range.
This would be like using an old for loop.
auto indices = hana::make_range(0_c, hana::length(handlers));
hana::for_each(indices, [&](auto i) {
handlers[i](nums[i]);
});
demo

Recursive lambda function c++ [duplicate]

I am new to C++11. I am writing the following recursive lambda function, but it doesn't compile.
sum.cpp
#include <iostream>
#include <functional>
auto term = [](int a)->int {
return a*a;
};
auto next = [](int a)->int {
return ++a;
};
auto sum = [term,next,&sum](int a, int b)mutable ->int {
if(a>b)
return 0;
else
return term(a) + sum(next(a),b);
};
int main(){
std::cout<<sum(1,10)<<std::endl;
return 0;
}
compilation error:
vimal#linux-718q:~/Study/09C++/c++0x/lambda> g++ -std=c++0x sum.cpp
sum.cpp: In lambda function:
sum.cpp:18:36: error: ‘((<lambda(int, int)>*)this)-><lambda(int, int)>::sum’ cannot be used as a function
gcc version
gcc version 4.5.0 20091231 (experimental) (GCC)
But if I change the declaration of sum() as below, it works:
std::function<int(int,int)> sum = [term,next,&sum](int a, int b)->int {
if(a>b)
return 0;
else
return term(a) + sum(next(a),b);
};
Could someone please throw light on this?
Think about the difference between the auto version and the fully specified type version. The auto keyword infers its type from whatever it's initialized with, but what you're initializing it with needs to know what its type is (in this case, the lambda closure needs to know the types it's capturing). Something of a chicken-and-egg problem.
On the other hand, a fully specified function object's type doesn't need to "know" anything about what is being assigned to it, and so the lambda's closure can likewise be fully informed about the types its capturing.
Consider this slight modification of your code and it may make more sense:
std::function<int(int,int)> sum;
sum = [term,next,&sum](int a, int b)->int {
if(a>b)
return 0;
else
return term(a) + sum(next(a),b);
};
Obviously, this wouldn't work with auto. Recursive lambda functions work perfectly well (at least they do in MSVC, where I have experience with them), it's just that they aren't really compatible with type inference.
The trick is to feed in the lambda implementation to itself as a parameter, not by capture.
const auto sum = [term,next](int a, int b) {
auto sum_impl=[term,next](int a,int b,auto& sum_ref) mutable {
if(a>b){
return 0;
}
return term(a) + sum_ref(next(a),b,sum_ref);
};
return sum_impl(a,b,sum_impl);
};
All problems in computer science can be solved by another level of indirection. I first found this easy trick at http://pedromelendez.com/blog/2015/07/16/recursive-lambdas-in-c14/
It does require C++14 while the question is on C++11, but perhaps interesting to most.
Going via std::function is also possible but can result in slower code. But not always. Have a look at the answers to std::function vs template
With C++14, it is now quite easy to make an efficient recursive lambda without having to incur the additional overhead of std::function, in just a few lines of code (with a small edit from the original to prevent the user from taking an accidental copy):
template <class F>
struct y_combinator {
F f; // the lambda will be stored here
// a forwarding operator():
template <class... Args>
decltype(auto) operator()(Args&&... args) const {
// we pass ourselves to f, then the arguments.
// [edit: Barry] pass in std::ref(*this) instead of *this
return f(std::ref(*this), std::forward<Args>(args)...);
}
};
// helper function that deduces the type of the lambda:
template <class F>
y_combinator<std::decay_t<F>> make_y_combinator(F&& f) {
return {std::forward<F>(f)};
}
with which your original sum attempt becomes:
auto sum = make_y_combinator([term,next](auto sum, int a, int b) {
if (a>b) {
return 0;
}
else {
return term(a) + sum(next(a),b);
}
});
I have another solution, but work only with stateless lambdas:
void f()
{
static int (*self)(int) = [](int i)->int { return i>0 ? self(i-1)*i : 1; };
std::cout<<self(10);
}
Trick here is that lambdas can access static variables and you can convert stateless ones to function pointer.
You can use it with standard lambdas:
void g()
{
int sum;
auto rec = [&sum](int i) -> int
{
static int (*inner)(int&, int) = [](int& _sum, int i)->int
{
_sum += i;
return i>0 ? inner(_sum, i-1)*i : 1;
};
return inner(sum, i);
};
}
Its work in GCC 4.7
You can make a lambda function call itself recursively. The only thing you need to do is to is to reference it through a function wrapper so that the compiler knows it's return and argument type (you can't capture a variable -- the lambda itself -- that hasn't been defined yet).
function<int (int)> f;
f = [&f](int x) {
if (x == 0) return 0;
return x + f(x-1);
};
printf("%d\n", f(10));
Be very careful not to run out of the scope of the wrapper f.
To make lambda recursive without using external classes and functions (like std::function or fixed-point combinator) one can use the following construction in C++14 (live example):
#include <utility>
#include <list>
#include <memory>
#include <iostream>
int main()
{
struct tree
{
int payload;
std::list< tree > children = {}; // std::list of incomplete type is allowed
};
std::size_t indent = 0;
// indication of result type here is essential
const auto print = [&] (const auto & self, const tree & node) -> void
{
std::cout << std::string(indent, ' ') << node.payload << '\n';
++indent;
for (const tree & t : node.children) {
self(self, t);
}
--indent;
};
print(print, {1, {{2, {{8}}}, {3, {{5, {{7}}}, {6}}}, {4}}});
}
prints:
1
2
8
3
5
7
6
4
Note, result type of lambda should be specified explicitly.
I ran a benchmark comparing a recursive function vs a recursive lambda function using the std::function<> capture method. With full optimizations enabled on clang version 4.1, the lambda version ran significantly slower.
#include <iostream>
#include <functional>
#include <chrono>
uint64_t sum1(int n) {
return (n <= 1) ? 1 : n + sum1(n - 1);
}
std::function<uint64_t(int)> sum2 = [&] (int n) {
return (n <= 1) ? 1 : n + sum2(n - 1);
};
auto const ITERATIONS = 10000;
auto const DEPTH = 100000;
template <class Func, class Input>
void benchmark(Func&& func, Input&& input) {
auto t1 = std::chrono::high_resolution_clock::now();
for (auto i = 0; i != ITERATIONS; ++i) {
func(input);
}
auto t2 = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(t2-t1).count();
std::cout << "Duration: " << duration << std::endl;
}
int main() {
benchmark(sum1, DEPTH);
benchmark(sum2, DEPTH);
}
Produces results:
Duration: 0 // regular function
Duration: 4027 // lambda function
(Note: I also confirmed with a version that took the inputs from cin, so as to eliminate compile time evaluation)
Clang also produces a compiler warning:
main.cc:10:29: warning: variable 'sum2' is uninitialized when used within its own initialization [-Wuninitialized]
Which is expected, and safe, but should be noted.
It's great to have a solution in our toolbelts, but I think the language will need a better way to handle this case if performance is to be comparable to current methods.
Note:
As a commenter pointed out, it seems latest version of VC++ has found a way to optimize this to the point of equal performance. Maybe we don't need a better way to handle this, after all (except for syntactic sugar).
Also, as some other SO posts have outlined in recent weeks, the performance of std::function<> itself may be the cause of slowdown vs calling function directly, at least when the lambda capture is too large to fit into some library-optimized space std::function uses for small-functors (I guess kinda like the various short string optimizations?).
This is a slightly simpler implementation of the fixpoint operator which makes it a little more obvious exactly what's going on.
#include <iostream>
#include <functional>
using namespace std;
template<typename T, typename... Args>
struct fixpoint
{
typedef function<T(Args...)> effective_type;
typedef function<T(const effective_type&, Args...)> function_type;
function_type f_nonr;
T operator()(Args... args) const
{
return f_nonr(*this, args...);
}
fixpoint(const function_type& p_f)
: f_nonr(p_f)
{
}
};
int main()
{
auto fib_nonr = [](const function<int(int)>& f, int n) -> int
{
return n < 2 ? n : f(n-1) + f(n-2);
};
auto fib = fixpoint<int,int>(fib_nonr);
for (int i = 0; i < 6; ++i)
{
cout << fib(i) << '\n';
}
}
C++ 14:
Here is a recursive anonymous stateless/no capture generic set of lambdas
that outputs all numbers from 1, 20
([](auto f, auto n, auto m) {
f(f, n, m);
})(
[](auto f, auto n, auto m) -> void
{
cout << typeid(n).name() << el;
cout << n << el;
if (n<m)
f(f, ++n, m);
},
1, 20);
If I understand correctly this is using the Y-combinator solution
And here is the sum(n, m) version
auto sum = [](auto n, auto m) {
return ([](auto f, auto n, auto m) {
int res = f(f, n, m);
return res;
})(
[](auto f, auto n, auto m) -> int
{
if (n > m)
return 0;
else {
int sum = n + f(f, n + 1, m);
return sum;
}
},
n, m); };
auto result = sum(1, 10); //result == 55
Here is the final answer for the OP. Anyway, Visual Studio 2010 does not support capturing global variables. And you do not need to capture them because global variable is accessable globally by define. The following answer uses local variable instead.
#include <functional>
#include <iostream>
template<typename T>
struct t2t
{
typedef T t;
};
template<typename R, typename V1, typename V2>
struct fixpoint
{
typedef std::function<R (V1, V2)> func_t;
typedef std::function<func_t (func_t)> tfunc_t;
typedef std::function<func_t (tfunc_t)> yfunc_t;
class loopfunc_t {
public:
func_t operator()(loopfunc_t v)const {
return func(v);
}
template<typename L>
loopfunc_t(const L &l):func(l){}
typedef V1 Parameter1_t;
typedef V2 Parameter2_t;
private:
std::function<func_t (loopfunc_t)> func;
};
static yfunc_t fix;
};
template<typename R, typename V1, typename V2>
typename fixpoint<R, V1, V2>::yfunc_t fixpoint<R, V1, V2>::fix = [](tfunc_t f) -> func_t {
return [f](fixpoint<R, V1, V2>::loopfunc_t x){ return f(x(x)); }
([f](fixpoint<R, V1, V2>::loopfunc_t x) -> fixpoint<R, V1, V2>::func_t{
auto &ff = f;
return [ff, x](t2t<decltype(x)>::t::Parameter1_t v1,
t2t<decltype(x)>::t::Parameter1_t v2){
return ff(x(x))(v1, v2);
};
});
};
int _tmain(int argc, _TCHAR* argv[])
{
auto term = [](int a)->int {
return a*a;
};
auto next = [](int a)->int {
return ++a;
};
auto sum = fixpoint<int, int, int>::fix(
[term,next](std::function<int (int, int)> sum1) -> std::function<int (int, int)>{
auto &term1 = term;
auto &next1 = next;
return [term1, next1, sum1](int a, int b)mutable ->int {
if(a>b)
return 0;
else
return term1(a) + sum1(next1(a),b);
};
});
std::cout<<sum(1,10)<<std::endl; //385
return 0;
}
You're trying to capture a variable (sum) you're in the middle of defining. That can't be good.
I don't think truely self-recursive C++0x lambdas are possible. You should be able to capture other lambdas, though.
This answer is inferior to Yankes' one, but still, here it goes:
using dp_type = void (*)();
using fp_type = void (*)(dp_type, unsigned, unsigned);
fp_type fp = [](dp_type dp, unsigned const a, unsigned const b) {
::std::cout << a << ::std::endl;
return reinterpret_cast<fp_type>(dp)(dp, b, a + b);
};
fp(reinterpret_cast<dp_type>(fp), 0, 1);
You need a fixed point combinator. See this.
or look at the following code:
//As decltype(variable)::member_name is invalid currently,
//the following template is a workaround.
//Usage: t2t<decltype(variable)>::t::member_name
template<typename T>
struct t2t
{
typedef T t;
};
template<typename R, typename V>
struct fixpoint
{
typedef std::function<R (V)> func_t;
typedef std::function<func_t (func_t)> tfunc_t;
typedef std::function<func_t (tfunc_t)> yfunc_t;
class loopfunc_t {
public:
func_t operator()(loopfunc_t v)const {
return func(v);
}
template<typename L>
loopfunc_t(const L &l):func(l){}
typedef V Parameter_t;
private:
std::function<func_t (loopfunc_t)> func;
};
static yfunc_t fix;
};
template<typename R, typename V>
typename fixpoint<R, V>::yfunc_t fixpoint<R, V>::fix =
[](fixpoint<R, V>::tfunc_t f) -> fixpoint<R, V>::func_t {
fixpoint<R, V>::loopfunc_t l = [f](fixpoint<R, V>::loopfunc_t x) ->
fixpoint<R, V>::func_t{
//f cannot be captured since it is not a local variable
//of this scope. We need a new reference to it.
auto &ff = f;
//We need struct t2t because template parameter
//V is not accessable in this level.
return [ff, x](t2t<decltype(x)>::t::Parameter_t v){
return ff(x(x))(v);
};
};
return l(l);
};
int _tmain(int argc, _TCHAR* argv[])
{
int v = 0;
std::function<int (int)> fac =
fixpoint<int, int>::fix([](std::function<int (int)> f)
-> std::function<int (int)>{
return [f](int i) -> int{
if(i==0) return 1;
else return i * f(i-1);
};
});
int i = fac(10);
std::cout << i; //3628800
return 0;
}

Resources