Reputation: 379
I already know how to make a recursive lambda function that take one argument like calculating factorial of a number, but I try to make a recursive power function using lambda (as a practice), but taking 2 arguments in the function caused errors
this the code :
std::function <int(int)> power = [&](int a, int n)
{
return (n<=1) ? a : a*power(a, n-1);
};
this line return (n<=1) ? a : a*power(a, n-1);
gives these errors :
error: no match for call to '(std::function<int(int)>) (int&, int)' note: candidate: _Res std::function<_Res(_ArgTypes ...)>::operator()(_ArgTypes ...) const [with _Res = int; _ArgTypes = {int}] note: candidate expects 1 argument, 2 provided
Upvotes: 1
Views: 181
Reputation: 275966
Your recursive lambda runs into a problem; it requires the exact variabke it was created in to exist, or it is UB to call it.
auto ycomb = [](auto&&f){ return [f=f](auto&&...args){ return f(f, decltype(args)(args)...); }; };
this little toy fixes that bug.
auto power = ycomb( [](auto&& self, int a, unsigned int n)->int
{
return (n==0) ? 1 : a*self(self, a, n-1);
});
there.
ycomb
is the ycombinator. It is famous.
This power
can be copied around and can outlive the scope of its construction safely.
If you don't like self(self, args...)
you can reuse ycombinator to make it:
auto ycomb0 = [](auto&&f){
return [=](auto&&...args){
return f(f, decltype(args)(args)...);
};
};
auto ycombx_ref = [](auto&& r, auto&& f) {
return [&r, f](auto&&...args) {
return f( r(r, f), decltype(args)(args)... );
};
};
auto ycomb = ycomb0( ycombx_ref );
and now the self
passed to the lambda doesn't itself need to be passed self:
auto power = ycomb( [](auto&& self, int a, unsigned int n)->int
{
return (n==0) ? 1 : a*self(a, n-1);
});
Upvotes: 0
Reputation: 206747
You'll have to use
std::function <int(int, int)> power = [&](int a, int n) { ... }
for the function to work with two arguments.
n = 0
correctly.Use of
return (n <= 1) ? a : a*power(a, n-1);
is not right. You will get back a
when the function is called with n = 0
.
Use
return (n == 0) ? 1 : a*power(a, n-1);
unsigned int
for n
.std::function <int(int, unsigned int)> power = [&](int a, unsigned int n) { ... }
Then, you won't have to worry about the function getting called with negative values for n
.
std::function <int(int, unsigned int)> power = [&](int a, unsigned int n)
{
return (n == 0) ? 1 : a*power(a, n-1);
};
Upvotes: 4
Reputation: 66230
Maybe
std::function <int(int, int)> power = [&](int a, int n) ....
// ...................^^^^^
?
I mean: if power
is a std::function
that is initialized with a lambda that receive two integers, and is uses as a functional that receive two integers, maybe is the case to declare it as receiving two integers, not only one.
Upvotes: 4