(About recursive lambdas)
<snip>
>> One solution would be to avoid using auto. To do this you pretty much
>> have to use std::function because lambdas that have a capture are not
>> convertible to function pointers. To take a simpler example:
>>
>> std::function<int(int)> f = [&f](int n) {
>> return n < 1 ? 1 : n * f(n-1);
>> };
>>
>> If the lambda has no capture, f could be a pointer to function object,
>> but then you could not refer to f in the body.
>>
>> There are some tricks you can play that simulate the effect of a Y
>> combinator, but these appeal to me simply on academic grounds. For
>> example I enjoyed the fact that this works with gcc:
>>
>> auto f = [](int n, auto g){
>> if (n < 1) return 1;
>> else return n * g(n-1, g);
>> };
>>
>> where the call now becomes f(5, f);
>>
>> However, switching back to the big picture, if expand is the only
>> thing captured, why not write a named function to do this?
>
> There was a proposal to add a Y-combinator to the standard library:
>
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0200r0.html .
> I don't know what became of it.
>
> However, there is a sample implementation which it says can be
> implemented in C++11/14 and which might interest you.
Yes, thanks. That was interesting. The document is, in effect, an
extended answer to the OP's question.
The proposed "combinator" essentially automates what I was doing with f
and g above and the suggested implementation does indeed work, though I
think it needs C++14.
Cutting and pasting the definition from that document, I can write:
auto f = std::y_combinator(
[](auto f, int n) -> int { return n < 1 ? 1 : n * f(n-1); }
);
std::cout << f(5) << "\n";
though gcc (v6.3 at least) is unable to deduce the type without the
-> int in there.
--
Ben.