The textbook functional programming introduction example "return a function with a curried parameter" in C does not compile for me:
// return a function x(v) parameterized with b, which tells if v > b
bool (*greater(int))(int b)
{
return [b](int v) { return v > b; };
}
It says that identifier b in the capture [b] is undefined. I know that I'm being naive here, but where is my error?
CodePudding user response:
You say that greater is a function taking an unnamed (anonymous) int argument, and return a pointer to a function taking an int argument with the name b.
The part (int b) is the argument list for the returned function pointer.
To solve that specific problem use
bool (*greater(int b))(int)
instead.
Because function pointers are so complicated, they are usually hidden behind type-aliases:
using greater_function_type = bool(int);
greater_function_type* greater(int b) { ... }
As for the problem that lambdas with captures can't be used as C-style function pointers, use std::function as return type instead:
using greater_function_type = std::function<bool(int)>;
greater_function_type greater(int b) { ... }
Note that it's not returning a pointer anymore.
Since the C 14 standard you can use automatic return-type deduction with the keyword auto:
auto greater(int b) { ... }
If you need to store the returned objects, for example as a class member variable, you need to use std::function<bool(int)> for that.
Also be careful when using names like greater in conjunction with using namespace std; (which is a bad habit), because of std::greater.
CodePudding user response:
Lambda is capturing [b], which cannot be converted to a function pointer. It requires std::function:
std::function<bool(int)> greater (int b) { ... }
If the function is expected to be inline then you may use simple auto as well:
auto greater (int b) { ... }
BTW, if b is not expected to change within the scope of greater(), then accept it as const int b instead f int b to be more expressive.
CodePudding user response:
Only lambdas without capture can be cast into a C style function pointer.
Lambdas with capture are actually classes with data members (one for each capture).
In your case you have one capture (b).
In order to return a curried function (which require a capture) you should use std::function:
#include <functional>
#include <iostream>
std::function<bool(int)> greater(int b)
{
auto l = [b](int v) { return v > b; };
return l;
}
int main()
{
auto g5 = greater(5);
std::cout << g5(2) << std::endl;
std::cout << g5(7) << std::endl;
}
Output:
0
1
