Topic: Lambda types and efficient recursion


Author: Diggory Blake <diggsey@googlemail.com>
Date: Tue, 6 May 2014 11:08:12 -0700 (PDT)
Raw View
------=_Part_1245_14860825.1399399692773
Content-Type: text/plain; charset=UTF-8

Apologies if this has already been addressed somewhere:

When declaring a lambda, the type of the lambda is not available until
after the body of the lambda has been compiled:

auto f = [&](int a){
   if (a == 0)
      return 0;
   else
      return f(a-1)+1; // This will fail: the type of 'f' is not yet known,
so it cannot be bound to the lambda
};

This is understandable, and in this case without a significantly smarter
compiler is impossible to avoid (AFAIK). To make a recursive lambda, you
therefore have to wrap it in a std::function:

std::function<int(int)> f = [&](int a){
   if (a == 0)
      return 0;
   else
      return f(a-1)+1; // This will work: the type of 'f' is already known,
as it does not depend on the type of the lambda
};

This obviously is much less efficient, and when tested, compilers were
unable to optimise away the indirect call.

It seems like there should be a special case where the compiler can
determine the type of a lambda before compiling the lambda body:

auto f = [&f](int a) -> int { // At the point of the capture list, the type
of 'f' is not fully defined, but is known to be a lambda (analogous to
declaration of struct without body) and can therefore be bound by reference
(but not value)
   if (a == 0)
      return 0;
   else
      return f(a-1)+1; // This should work: the type of the lambda was
fully determined by the capture list, parameters and return type
};

When the capture list, parameters and return type are all explicitly
specified, then the type of the lambda should be known within the lambda
body.

Thoughts?

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_1245_14860825.1399399692773
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Apologies if this has already been addressed somewhere:<br=
><br>When declaring a lambda, the type of the lambda is not available until=
 after the body of the lambda has been compiled:<br><br><span style=3D"font=
-family: courier new,monospace;">auto f =3D [&amp;](int a){<br>&nbsp;&nbsp;=
 if (a =3D=3D 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>&nbsp;&nbsp=
; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return f(a-1)+1; // This will fail=
: the type of 'f' is not yet known, so it cannot be bound to the lambda<br>=
};</span><br><br>This is understandable, and in this case without a signifi=
cantly smarter compiler is impossible to avoid (AFAIK). To make a recursive=
 lambda, you therefore have to wrap it in a std::function:<br><br><span sty=
le=3D"font-family: courier new,monospace;">std::function&lt;int(int)&gt; f =
=3D  [&amp;](int a){<br>&nbsp;&nbsp; if (a =3D=3D 0)<br>&nbsp;&nbsp;&nbsp;&=
nbsp;&nbsp; return 0;<br>&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp=
; return f(a-1)+1; // This will work: the type of 'f' is already known, as =
it does not depend on the type of the lambda<br>};</span><br><br>This obvio=
usly is much less efficient, and when tested, compilers were unable to opti=
mise away the indirect call.<br><br>It seems like there should be a special=
 case where the compiler can determine the type of a lambda before compilin=
g the lambda body:<br><br><span style=3D"font-family: courier new,monospace=
;">auto f =3D [&amp;f](int a) -&gt; int { // At the point of the capture li=
st, the type of 'f' is not fully defined, but is known to be a lambda (anal=
ogous to declaration of struct without body) and can therefore be bound by =
reference (but not value)<br>&nbsp;&nbsp; if (a =3D=3D 0)<br>&nbsp;&nbsp;&n=
bsp;&nbsp;&nbsp; return 0;<br>&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;=
&nbsp; return f(a-1)+1; // This should work: the type of the lambda was ful=
ly determined by the capture list, parameters and return type<br>};</span><=
br><br>When the capture list, parameters and return type are all explicitly=
 specified, then the type of the lambda should be known within the lambda b=
ody.<br><br>Thoughts?<br></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_1245_14860825.1399399692773--

.


Author: Diggory Blake <diggsey@googlemail.com>
Date: Tue, 6 May 2014 12:26:10 -0700 (PDT)
Raw View
------=_Part_2302_22845720.1399404370953
Content-Type: text/plain; charset=UTF-8

Thanks for pointing that out, however, it doesn't prevent the lambda's type
from being available within the lambda, it only prevents the type of 'f'
from being known at the point of the capture list.

Your suggestion is nice, but I think it's important that the lambda can
access its own type - what about this:

template<typename T> memoized<T> memoize(T functor) { /* return a callable
object which caches calls to the functor */ }

lambda lam; // The identity of the lambda is determined here, although its
type is not yet fully defined.
memoized<lam> f = memoize([&f]lam(int a) -> int {
   return a > 1 ? f(a - 1) + f(a - 2) : a;
}

I'm sure there's better syntax for this, and there's potentially an issue
about when the template is instantiated, but there are at least a couple of
important cases that named lambdas alone, the way you suggested, wouldn't
solve:
- Adding modifiers to lambdas such as the memoization one above
- Mutually recursive lambdas

Not saying it has to be done this way, it's just something that should at
least be possible.

On Tuesday, 6 May 2014 19:35:07 UTC+1, Richard Smith wrote:
>
> On Tue, May 6, 2014 at 11:08 AM, Diggory Blake <dig...@googlemail.com<javascript:>
> > wrote:
>
>> Apologies if this has already been addressed somewhere:
>>
>> When declaring a lambda, the type of the lambda is not available until
>> after the body of the lambda has been compiled:
>>
>> auto f = [&](int a){
>>    if (a == 0)
>>       return 0;
>>    else
>>       return f(a-1)+1; // This will fail: the type of 'f' is not yet
>> known, so it cannot be bound to the lambda
>> };
>>
>> This is understandable, and in this case without a significantly smarter
>> compiler is impossible to avoid (AFAIK). To make a recursive lambda, you
>> therefore have to wrap it in a std::function:
>>
>> std::function<int(int)> f = [&](int a){
>>    if (a == 0)
>>       return 0;
>>    else
>>       return f(a-1)+1; // This will work: the type of 'f' is already
>> known, as it does not depend on the type of the lambda
>> };
>>
>> This obviously is much less efficient, and when tested, compilers were
>> unable to optimise away the indirect call.
>>
>> It seems like there should be a special case where the compiler can
>> determine the type of a lambda before compiling the lambda body:
>>
>> auto f = [&f](int a) -> int { // At the point of the capture list, the
>> type of 'f' is not fully defined, but is known to be a lambda (analogous to
>> declaration of struct without body) and can therefore be bound by reference
>> (but not value)
>>    if (a == 0)
>>       return 0;
>>    else
>>       return f(a-1)+1; // This should work: the type of the lambda was
>> fully determined by the capture list, parameters and return type
>> };
>>
>> When the capture list, parameters and return type are all explicitly
>> specified, then the type of the lambda should be known within the lambda
>> body.
>>
>> Thoughts?
>>
>
> Think about this:
>
> auto f = [&f](int a) -> int { // At the point of the capture list, the
> type of 'f' is not fully defined, but is known to be a lambda (analogous to
> declaration of struct without body) and can therefore be bound by reference
> (but not value)
>    if (a == 0)
>       return 0;
>    else
>       return f(a-1)+1; // This should work: the type of the lambda was
> fully determined by the capture list, parameters and return type
> }() ? foo : bar; // oops, f isn't what you thought it was
>
> => Your proposal doesn't quite work, unless you expect the compiler to
> look ahead past the body of the lambda. It's also a *very* special case.
>
> Things like this also don't quite work:
>
> auto f = [&f](int a) { return a > 1 ? f(a - 1) + f(a - 2) : a; }
> // then store 'f' somewhere
>
> ... because the 'f' that the lambda refers to may have gone out of scope
> by the time the lambda is invoked.
>
> Here's an alternative:
>
> auto f = [&]f(int a) -> int { // name the lambda
>   return a > 1 ? f(a - 1) + f(a - 2) : a; // uses of the lambda's name are
> transformed to uses of the lambda's operator()
> }
>
> Note that we cannot make 'f' refer to the lambda object, because its type
> is not complete within the lambda's body. But we can support recursive
> lambdas this way.
>
> --
>>
>> ---
>> You received this message because you are subscribed to the Google Groups
>> "ISO C++ Standard - Future Proposals" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to std-proposal...@isocpp.org <javascript:>.
>> To post to this group, send email to std-pr...@isocpp.org <javascript:>.
>> Visit this group at
>> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>>
>
>

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_2302_22845720.1399404370953
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Thanks for pointing that out, however, it doesn't prevent =
the lambda's type from being available within the lambda, it only prevents =
the type of 'f' from being known at the point of the capture list.<br><br>Y=
our suggestion is nice, but I think it's important that the lambda can acce=
ss its own type - what about this:<br><br><span style=3D"font-family: couri=
er new,monospace;">template&lt;typename T&gt; memoized&lt;T&gt; memoize(T f=
unctor) { /* return a callable object which caches calls to the functor */ =
}<br><br>lambda lam; // The identity of the lambda is determined here, alth=
ough its type is not yet fully defined.<br></span><span style=3D"font-famil=
y: courier new,monospace;"><span style=3D"font-family: courier new,monospac=
e;">memoized&lt;lam&gt;</span> f =3D memoize([&amp;f]lam(int a) -&gt; int {=
<br>&nbsp;&nbsp; return a &gt; 1 ? f(a - 1) + f(a - 2) : a;<br>}</span><br>=
<br>I'm sure there's better syntax for this, and there's potentially an iss=
ue about when the template is instantiated, but there are at least a couple=
 of important cases that named lambdas alone, the way you suggested, wouldn=
't solve:<br>- Adding modifiers to lambdas such as the memoization one abov=
e<br>- Mutually recursive lambdas<br><br>Not saying it has to be done this =
way, it's just something that should at least be possible.<br><br>On Tuesda=
y, 6 May 2014 19:35:07 UTC+1, Richard Smith  wrote:<blockquote class=3D"gma=
il_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid=
;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote">On Tu=
e, May 6, 2014 at 11:08 AM, Diggory Blake <span dir=3D"ltr">&lt;<a href=3D"=
javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"hM4EqsRPGagJ" onmou=
sedown=3D"this.href=3D'javascript:';return true;" onclick=3D"this.href=3D'j=
avascript:';return true;">dig...@googlemail.com</a>&gt;</span> wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p=
adding-left:1ex"><div dir=3D"ltr">Apologies if this has already been addres=
sed somewhere:<br>
<br>When declaring a lambda, the type of the lambda is not available until =
after the body of the lambda has been compiled:<br><br><span style=3D"font-=
family:'courier new',monospace">auto f =3D [&amp;](int a){<br>&nbsp;&nbsp; =
if (a =3D=3D 0)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>&nbsp;&nbsp; else<br>&nbsp;&nbs=
p;&nbsp;&nbsp;&nbsp; return f(a-1)+1; // This will fail: the type of 'f' is=
 not yet known, so it cannot be bound to the lambda<br>};</span><br><br>Thi=
s is understandable, and in this case without a significantly smarter compi=
ler is impossible to avoid (AFAIK). To make a recursive lambda, you therefo=
re have to wrap it in a std::function:<br>
<br><span style=3D"font-family:'courier new',monospace">std::function&lt;in=
t(int)&gt; f =3D  [&amp;](int a){<br>&nbsp;&nbsp; if (a =3D=3D 0)<br>&nbsp;=
&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbs=
p;&nbsp;&nbsp; return f(a-1)+1; // This will work: the type of 'f' is alrea=
dy known, as it does not depend on the type of the lambda<br>
};</span><br><br>This obviously is much less efficient, and when tested, co=
mpilers were unable to optimise away the indirect call.<br><br>It seems lik=
e there should be a special case where the compiler can determine the type =
of a lambda before compiling the lambda body:<br>
<br><span style=3D"font-family:'courier new',monospace">auto f =3D [&amp;f]=
(int a) -&gt; int { // At the point of the capture list, the type of 'f' is=
 not fully defined, but is known to be a lambda (analogous to declaration o=
f struct without body) and can therefore be bound by reference (but not val=
ue)<br>
&nbsp;&nbsp; if (a =3D=3D 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br=
>&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return f(a-1)+1; // Th=
is should work: the type of the lambda was fully determined by the capture =
list, parameters and return type<br>};</span><br><br>When the capture list,=
 parameters and return type are all explicitly specified, then the type of =
the lambda should be known within the lambda body.<br>
<br>Thoughts?</div></blockquote><div><br></div><div>Think about this:</div>=
<div><br></div><div><span style=3D"font-size:13px;font-family:'courier new'=
,monospace">auto f =3D [&amp;f](int a) -&gt; int { // At the point of the c=
apture list, the type of 'f' is not fully defined, but is known to be a lam=
bda (analogous to declaration of struct without body) and can therefore be =
bound by reference (but not value)<br>
&nbsp;&nbsp; if (a =3D=3D 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br=
>&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return f(a-1)+1; // Th=
is should work: the type of the lambda was fully determined by the capture =
list, parameters and return type<br>}() ? foo : bar; // oops, f isn't what =
you thought it was</span><br style=3D"font-family:arial,sans-serif;font-siz=
e:13px">
</div><div><br></div><div>=3D&gt; Your proposal doesn't quite work, unless =
you expect the compiler to look ahead past the body of the lambda. It's als=
o a *very* special case.</div><div><br></div><div>Things like this also don=
't quite work:</div>
<div><br></div><div><font face=3D"courier new, monospace">auto f =3D [&amp;=
f](int a) { return a &gt; 1 ? f(a - 1) + f(a - 2) : a; }</font></div><div><=
font face=3D"courier new, monospace">// then store 'f' somewhere</font></di=
v>
<div><br></div><div>... because the 'f' that the lambda refers to may have =
gone out of scope by the time the lambda is invoked.</div><div><br></div><d=
iv>Here's an alternative:</div><div><br></div><div><div><font face=3D"couri=
er new, monospace">auto f =3D [&amp;]f(int a) -&gt; int { // name the lambd=
a</font></div>
<div><font face=3D"courier new, monospace">&nbsp; return a &gt; 1 ? f(a - 1=
) + f(a - 2) : a; // uses of the lambda's name are transformed to uses of t=
he lambda's operator()</font></div><div><font face=3D"courier new, monospac=
e">}</font></div>
</div><div><br></div><div>Note that we cannot make 'f' refer to the lambda =
object, because its type is not complete within the lambda's body. But we c=
an support recursive lambdas this way.</div><div><br></div>
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p=
adding-left:1ex"><div dir=3D"ltr"><span style=3D"color:rgb(136,136,136)">--=
&nbsp;</span></div>
<span><font color=3D"#888888">
<br>
--- <br>
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"=
hM4EqsRPGagJ" onmousedown=3D"this.href=3D'javascript:';return true;" onclic=
k=3D"this.href=3D'javascript:';return true;">std-proposal...@<wbr>isocpp.or=
g</a>.<br>
To post to this group, send email to <a href=3D"javascript:" target=3D"_bla=
nk" gdf-obfuscated-mailto=3D"hM4EqsRPGagJ" onmousedown=3D"this.href=3D'java=
script:';return true;" onclick=3D"this.href=3D'javascript:';return true;">s=
td-pr...@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank" onmousedown=3D"this.href=3D'http://groups=
..google.com/a/isocpp.org/group/std-proposals/';return true;" onclick=3D"thi=
s.href=3D'http://groups.google.com/a/isocpp.org/group/std-proposals/';retur=
n true;">http://groups.google.com/a/<wbr>isocpp.org/group/std-<wbr>proposal=
s/</a>.<br>
</font></span></blockquote></div><br></div></div>
</blockquote></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_2302_22845720.1399404370953--

.


Author: Richard Smith <richard@metafoo.co.uk>
Date: Tue, 6 May 2014 11:35:07 -0700
Raw View
--047d7b3a8f2cd5a5e304f8bf81a3
Content-Type: text/plain; charset=UTF-8

On Tue, May 6, 2014 at 11:08 AM, Diggory Blake <diggsey@googlemail.com>wrote:

> Apologies if this has already been addressed somewhere:
>
> When declaring a lambda, the type of the lambda is not available until
> after the body of the lambda has been compiled:
>
> auto f = [&](int a){
>    if (a == 0)
>       return 0;
>    else
>       return f(a-1)+1; // This will fail: the type of 'f' is not yet
> known, so it cannot be bound to the lambda
> };
>
> This is understandable, and in this case without a significantly smarter
> compiler is impossible to avoid (AFAIK). To make a recursive lambda, you
> therefore have to wrap it in a std::function:
>
> std::function<int(int)> f = [&](int a){
>    if (a == 0)
>       return 0;
>    else
>       return f(a-1)+1; // This will work: the type of 'f' is already
> known, as it does not depend on the type of the lambda
> };
>
> This obviously is much less efficient, and when tested, compilers were
> unable to optimise away the indirect call.
>
> It seems like there should be a special case where the compiler can
> determine the type of a lambda before compiling the lambda body:
>
> auto f = [&f](int a) -> int { // At the point of the capture list, the
> type of 'f' is not fully defined, but is known to be a lambda (analogous to
> declaration of struct without body) and can therefore be bound by reference
> (but not value)
>    if (a == 0)
>       return 0;
>    else
>       return f(a-1)+1; // This should work: the type of the lambda was
> fully determined by the capture list, parameters and return type
> };
>
> When the capture list, parameters and return type are all explicitly
> specified, then the type of the lambda should be known within the lambda
> body.
>
> Thoughts?
>

Think about this:

auto f = [&f](int a) -> int { // At the point of the capture list, the type
of 'f' is not fully defined, but is known to be a lambda (analogous to
declaration of struct without body) and can therefore be bound by reference
(but not value)
   if (a == 0)
      return 0;
   else
      return f(a-1)+1; // This should work: the type of the lambda was
fully determined by the capture list, parameters and return type
}() ? foo : bar; // oops, f isn't what you thought it was

=> Your proposal doesn't quite work, unless you expect the compiler to look
ahead past the body of the lambda. It's also a *very* special case.

Things like this also don't quite work:

auto f = [&f](int a) { return a > 1 ? f(a - 1) + f(a - 2) : a; }
// then store 'f' somewhere

.... because the 'f' that the lambda refers to may have gone out of scope by
the time the lambda is invoked.

Here's an alternative:

auto f = [&]f(int a) -> int { // name the lambda
  return a > 1 ? f(a - 1) + f(a - 2) : a; // uses of the lambda's name are
transformed to uses of the lambda's operator()
}

Note that we cannot make 'f' refer to the lambda object, because its type
is not complete within the lambda's body. But we can support recursive
lambdas this way.

--
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

--047d7b3a8f2cd5a5e304f8bf81a3
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On T=
ue, May 6, 2014 at 11:08 AM, Diggory Blake <span dir=3D"ltr">&lt;<a href=3D=
"mailto:diggsey@googlemail.com" target=3D"_blank">diggsey@googlemail.com</a=
>&gt;</span> wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p=
adding-left:1ex"><div dir=3D"ltr">Apologies if this has already been addres=
sed somewhere:<br>
<br>When declaring a lambda, the type of the lambda is not available until =
after the body of the lambda has been compiled:<br><br><span style=3D"font-=
family:&#39;courier new&#39;,monospace">auto f =3D [&amp;](int a){<br>=C2=
=A0=C2=A0 if (a =3D=3D 0)<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return 0;<br>=C2=A0=C2=A0 else<br>=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0 return f(a-1)+1; // This will fail: the type of &#39;=
f&#39; is not yet known, so it cannot be bound to the lambda<br>};</span><b=
r><br>This is understandable, and in this case without a significantly smar=
ter compiler is impossible to avoid (AFAIK). To make a recursive lambda, yo=
u therefore have to wrap it in a std::function:<br>
<br><span style=3D"font-family:&#39;courier new&#39;,monospace">std::functi=
on&lt;int(int)&gt; f =3D  [&amp;](int a){<br>=C2=A0=C2=A0 if (a =3D=3D 0)<b=
r>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return 0;<br>=C2=A0=C2=A0 else<br>=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0 return f(a-1)+1; // This will work: the type of &#=
39;f&#39; is already known, as it does not depend on the type of the lambda=
<br>
};</span><br><br>This obviously is much less efficient, and when tested, co=
mpilers were unable to optimise away the indirect call.<br><br>It seems lik=
e there should be a special case where the compiler can determine the type =
of a lambda before compiling the lambda body:<br>
<br><span style=3D"font-family:&#39;courier new&#39;,monospace">auto f =3D =
[&amp;f](int a) -&gt; int { // At the point of the capture list, the type o=
f &#39;f&#39; is not fully defined, but is known to be a lambda (analogous =
to declaration of struct without body) and can therefore be bound by refere=
nce (but not value)<br>
=C2=A0=C2=A0 if (a =3D=3D 0)<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return 0;<br=
>=C2=A0=C2=A0 else<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return f(a-1)+1; // Th=
is should work: the type of the lambda was fully determined by the capture =
list, parameters and return type<br>};</span><br><br>When the capture list,=
 parameters and return type are all explicitly specified, then the type of =
the lambda should be known within the lambda body.<br>
<br>Thoughts?</div></blockquote><div><br></div><div>Think about this:</div>=
<div><br></div><div><span style=3D"font-size:13px;font-family:&#39;courier =
new&#39;,monospace">auto f =3D [&amp;f](int a) -&gt; int { // At the point =
of the capture list, the type of &#39;f&#39; is not fully defined, but is k=
nown to be a lambda (analogous to declaration of struct without body) and c=
an therefore be bound by reference (but not value)<br>
=C2=A0=C2=A0 if (a =3D=3D 0)<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return 0;<br=
>=C2=A0=C2=A0 else<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return f(a-1)+1; // Th=
is should work: the type of the lambda was fully determined by the capture =
list, parameters and return type<br>}() ? foo : bar; // oops, f isn&#39;t w=
hat you thought it was</span><br style=3D"font-family:arial,sans-serif;font=
-size:13px">
</div><div><br></div><div>=3D&gt; Your proposal doesn&#39;t quite work, unl=
ess you expect the compiler to look ahead past the body of the lambda. It&#=
39;s also a *very* special case.</div><div><br></div><div>Things like this =
also don&#39;t quite work:</div>
<div><br></div><div><font face=3D"courier new, monospace">auto f =3D [&amp;=
f](int a) { return a &gt; 1 ? f(a - 1) + f(a - 2) : a; }</font></div><div><=
font face=3D"courier new, monospace">// then store &#39;f&#39; somewhere</f=
ont></div>
<div><br></div><div>... because the &#39;f&#39; that the lambda refers to m=
ay have gone out of scope by the time the lambda is invoked.</div><div><br>=
</div><div>Here&#39;s an alternative:</div><div><br></div><div><div><font f=
ace=3D"courier new, monospace">auto f =3D [&amp;]f(int a) -&gt; int { // na=
me the lambda</font></div>
<div><font face=3D"courier new, monospace">=C2=A0 return a &gt; 1 ? f(a - 1=
) + f(a - 2) : a; // uses of the lambda&#39;s name are transformed to uses =
of the lambda&#39;s operator()</font></div><div><font face=3D"courier new, =
monospace">}</font></div>
</div><div><br></div><div>Note that we cannot make &#39;f&#39; refer to the=
 lambda object, because its type is not complete within the lambda&#39;s bo=
dy. But we can support recursive lambdas this way.</div><div><br></div>
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p=
adding-left:1ex"><div dir=3D"ltr"><span style=3D"color:rgb(136,136,136)">--=
=C2=A0</span></div>
<span class=3D""><font color=3D"#888888">
<br>
--- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_=
blank">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</font></span></blockquote></div><br></div></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--047d7b3a8f2cd5a5e304f8bf81a3--

.


Author: Alex B <devalexb@gmail.com>
Date: Tue, 6 May 2014 12:56:05 -0700 (PDT)
Raw View
------=_Part_4697_28848297.1399406165568
Content-Type: text/plain; charset=UTF-8

For the record, here is a small (not so elegant) workaround using generic
lambdas:

auto f = [](int a)
{
    auto f2 = [](int a, auto f2)
    {
        if (a == 0)
            return 0;
        else
            return f2(a-1, f2);
    };
    f2(a, f2);
};


On Tuesday, May 6, 2014 2:08:12 PM UTC-4, Diggory Blake wrote:

> Apologies if this has already been addressed somewhere:
>
> When declaring a lambda, the type of the lambda is not available until
> after the body of the lambda has been compiled:
>
> auto f = [&](int a){
>    if (a == 0)
>       return 0;
>    else
>       return f(a-1)+1; // This will fail: the type of 'f' is not yet
> known, so it cannot be bound to the lambda
> };
>
> This is understandable, and in this case without a significantly smarter
> compiler is impossible to avoid (AFAIK). To make a recursive lambda, you
> therefore have to wrap it in a std::function:
>
> std::function<int(int)> f = [&](int a){
>    if (a == 0)
>       return 0;
>    else
>       return f(a-1)+1; // This will work: the type of 'f' is already
> known, as it does not depend on the type of the lambda
> };
>
> This obviously is much less efficient, and when tested, compilers were
> unable to optimise away the indirect call.
>
> It seems like there should be a special case where the compiler can
> determine the type of a lambda before compiling the lambda body:
>
> auto f = [&f](int a) -> int { // At the point of the capture list, the
> type of 'f' is not fully defined, but is known to be a lambda (analogous to
> declaration of struct without body) and can therefore be bound by reference
> (but not value)
>    if (a == 0)
>       return 0;
>    else
>       return f(a-1)+1; // This should work: the type of the lambda was
> fully determined by the capture list, parameters and return type
> };
>
> When the capture list, parameters and return type are all explicitly
> specified, then the type of the lambda should be known within the lambda
> body.
>
> Thoughts?
>

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_4697_28848297.1399406165568
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div>For the record, here is a small (not so elegant) work=
around using generic lambdas:</div><div>&nbsp;</div><div><div class=3D"pret=
typrint" style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-wo=
rd; background-color: rgb(250, 250, 250);"><code class=3D"prettyprint"><div=
 class=3D"subprettyprint"><span class=3D"styled-by-prettify" style=3D"color=
: rgb(0, 0, 136);">auto</span><span class=3D"styled-by-prettify" style=3D"c=
olor: rgb(0, 0, 0);"> f </span><span class=3D"styled-by-prettify" style=3D"=
color: rgb(102, 102, 0);">=3D</span><span class=3D"styled-by-prettify" styl=
e=3D"color: rgb(0, 0, 0);"> </span><span class=3D"styled-by-prettify" style=
=3D"color: rgb(102, 102, 0);">[](</span><span class=3D"styled-by-prettify" =
style=3D"color: rgb(0, 0, 136);">int</span><span class=3D"styled-by-prettif=
y" style=3D"color: rgb(0, 0, 0);"> a</span><span class=3D"styled-by-prettif=
y" style=3D"color: rgb(102, 102, 0);">)</span><span class=3D"styled-by-pret=
tify" style=3D"color: rgb(0, 0, 0);"><br></span><span class=3D"styled-by-pr=
ettify" style=3D"color: rgb(102, 102, 0);">{</span><span class=3D"styled-by=
-prettify" style=3D"color: rgb(0, 0, 0);"><br>&nbsp; &nbsp; </span><span cl=
ass=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);">auto</span><spa=
n class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> f2 </span><s=
pan class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">=3D</sp=
an><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> </spa=
n><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">[](=
</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);">=
int</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
> a</span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, =
0);">,</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0=
);"> </span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 13=
6);">auto</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0=
, 0);"> f2</span><span class=3D"styled-by-prettify" style=3D"color: rgb(102=
, 102, 0);">)</span><span class=3D"styled-by-prettify" style=3D"color: rgb(=
0, 0, 0);"><br>&nbsp; &nbsp; </span><span class=3D"styled-by-prettify" styl=
e=3D"color: rgb(102, 102, 0);">{</span><span class=3D"styled-by-prettify" s=
tyle=3D"color: rgb(0, 0, 0);"><br>&nbsp; &nbsp; &nbsp; &nbsp; </span><span =
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);">if</span><spa=
n class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> </span><span=
 class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">(</span><s=
pan class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);">a </span><s=
pan class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">=3D=3D<=
/span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> </=
span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 102, 102);">=
0</span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0)=
;">)</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);=
"><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class=3D"style=
d-by-prettify" style=3D"color: rgb(0, 0, 136);">return</span><span class=3D=
"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> </span><span class=3D"=
styled-by-prettify" style=3D"color: rgb(0, 102, 102);">0</span><span class=
=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">;</span><span cl=
ass=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"><br>&nbsp; &nbsp;=
 &nbsp; &nbsp; </span><span class=3D"styled-by-prettify" style=3D"color: rg=
b(0, 0, 136);">else</span><span class=3D"styled-by-prettify" style=3D"color=
: rgb(0, 0, 0);"><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span=
 class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);">return</span=
><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> f2</spa=
n><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">(</=
span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);">a</s=
pan><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">-=
</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 102, 102);=
">1</span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, =
0);">,</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0=
);"> f2</span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 1=
02, 0);">);</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0,=
 0, 0);"><br>&nbsp; &nbsp; </span><span class=3D"styled-by-prettify" style=
=3D"color: rgb(102, 102, 0);">};</span><span class=3D"styled-by-prettify" s=
tyle=3D"color: rgb(0, 0, 0);"><br>&nbsp; &nbsp; f2</span><span class=3D"sty=
led-by-prettify" style=3D"color: rgb(102, 102, 0);">(</span><span class=3D"=
styled-by-prettify" style=3D"color: rgb(0, 0, 0);">a</span><span class=3D"s=
tyled-by-prettify" style=3D"color: rgb(102, 102, 0);">,</span><span class=
=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> f2</span><span clas=
s=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">);</span><span =
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"><br></span><spa=
n class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">};</span>=
</div></code></div><br></div><div><br>On Tuesday, May 6, 2014 2:08:12 PM UT=
C-4, Diggory Blake wrote:</div><blockquote class=3D"gmail_quote" style=3D"m=
argin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 20=
4, 204); border-left-width: 1px; border-left-style: solid;"><div dir=3D"ltr=
">Apologies if this has already been addressed somewhere:<br><br>When decla=
ring a lambda, the type of the lambda is not available until after the body=
 of the lambda has been compiled:<br><br><span style=3D"font-family: courie=
r new,monospace;">auto f =3D [&amp;](int a){<br>&nbsp;&nbsp; if (a =3D=3D 0=
)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>&nbsp;&nbsp; else<br>&nbsp=
;&nbsp;&nbsp;&nbsp;&nbsp; return f(a-1)+1; // This will fail: the type of '=
f' is not yet known, so it cannot be bound to the lambda<br>};</span><br><b=
r>This is understandable, and in this case without a significantly smarter =
compiler is impossible to avoid (AFAIK). To make a recursive lambda, you th=
erefore have to wrap it in a std::function:<br><br><span style=3D"font-fami=
ly: courier new,monospace;">std::function&lt;int(int)&gt; f =3D  [&amp;](in=
t a){<br>&nbsp;&nbsp; if (a =3D=3D 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret=
urn 0;<br>&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return f(a-1)=
+1; // This will work: the type of 'f' is already known, as it does not dep=
end on the type of the lambda<br>};</span><br><br>This obviously is much le=
ss efficient, and when tested, compilers were unable to optimise away the i=
ndirect call.<br><br>It seems like there should be a special case where the=
 compiler can determine the type of a lambda before compiling the lambda bo=
dy:<br><br><span style=3D"font-family: courier new,monospace;">auto f =3D [=
&amp;f](int a) -&gt; int { // At the point of the capture list, the type of=
 'f' is not fully defined, but is known to be a lambda (analogous to declar=
ation of struct without body) and can therefore be bound by reference (but =
not value)<br>&nbsp;&nbsp; if (a =3D=3D 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp=
; return 0;<br>&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return f=
(a-1)+1; // This should work: the type of the lambda was fully determined b=
y the capture list, parameters and return type<br>};</span><br><br>When the=
 capture list, parameters and return type are all explicitly specified, the=
n the type of the lambda should be known within the lambda body.<br><br>Tho=
ughts?<br></div></blockquote></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_4697_28848297.1399406165568--

.


Author: Diggory Blake <diggsey@googlemail.com>
Date: Tue, 6 May 2014 16:50:29 -0700 (PDT)
Raw View
------=_Part_1536_12544599.1399420229711
Content-Type: text/plain; charset=UTF-8

Correction, that should be:
template<typename T, typename U> auto bind_modifier(U functor) {
   T modifier;
   return std::bind(modifier(functor), modifier(functor));
}

And the modifier would have to be aware of the extra first parameter.

On Wednesday, 7 May 2014 00:47:01 UTC+1, Diggory Blake wrote:
>
> Interesting, I came up with this based on that idea:
>
> struct memoize {
>    template<typename T> memoized<T> operator()(T functor) { /* return a
> callable object which caches calls to the functor */ }
> };
>
> template<typename T, typename U> auto bind_modifier(U functor) {
>    T modifier;
>    return std::bind(functor, modifier(functor));
> }
>
> auto f = bind_modifier<memoize>([](auto& f, int a) {
>    return a > 1 ? f(f, a-1) + f(f, a-2) : a;
> });
>
> I really like the syntax here as it means you can change the modifiers
> without altering the lambda code. The only bit I'm concerned about is
> whether the compiler would be able to optimise away the extra parameter.
>
> On Tuesday, 6 May 2014 20:56:05 UTC+1, Alex B wrote:
>>
>> For the record, here is a small (not so elegant) workaround using generic
>> lambdas:
>>
>> auto f = [](int a)
>> {
>>     auto f2 = [](int a, auto f2)
>>     {
>>         if (a == 0)
>>             return 0;
>>         else
>>             return f2(a-1, f2);
>>     };
>>     f2(a, f2);
>> };
>>
>>
>> On Tuesday, May 6, 2014 2:08:12 PM UTC-4, Diggory Blake wrote:
>>
>>> Apologies if this has already been addressed somewhere:
>>>
>>> When declaring a lambda, the type of the lambda is not available until
>>> after the body of the lambda has been compiled:
>>>
>>> auto f = [&](int a){
>>>    if (a == 0)
>>>       return 0;
>>>    else
>>>       return f(a-1)+1; // This will fail: the type of 'f' is not yet
>>> known, so it cannot be bound to the lambda
>>> };
>>>
>>> This is understandable, and in this case without a significantly smarter
>>> compiler is impossible to avoid (AFAIK). To make a recursive lambda, you
>>> therefore have to wrap it in a std::function:
>>>
>>> std::function<int(int)> f = [&](int a){
>>>    if (a == 0)
>>>       return 0;
>>>    else
>>>       return f(a-1)+1; // This will work: the type of 'f' is already
>>> known, as it does not depend on the type of the lambda
>>> };
>>>
>>> This obviously is much less efficient, and when tested, compilers were
>>> unable to optimise away the indirect call.
>>>
>>> It seems like there should be a special case where the compiler can
>>> determine the type of a lambda before compiling the lambda body:
>>>
>>> auto f = [&f](int a) -> int { // At the point of the capture list, the
>>> type of 'f' is not fully defined, but is known to be a lambda (analogous to
>>> declaration of struct without body) and can therefore be bound by reference
>>> (but not value)
>>>    if (a == 0)
>>>       return 0;
>>>    else
>>>       return f(a-1)+1; // This should work: the type of the lambda was
>>> fully determined by the capture list, parameters and return type
>>> };
>>>
>>> When the capture list, parameters and return type are all explicitly
>>> specified, then the type of the lambda should be known within the lambda
>>> body.
>>>
>>> Thoughts?
>>>
>>

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_1536_12544599.1399420229711
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Correction, that should be:<br><span style=3D"font-family:=
courier new,monospace">template&lt;typename T, typename U&gt; auto bind_mod=
ifier(U functor) {<br>&nbsp;&nbsp; T modifier;<br>&nbsp;&nbsp; return std::=
bind(modifier(functor), modifier(functor));<br>}</span><br><br>And the modi=
fier would have to be aware of the extra first parameter.<br><br>On Wednesd=
ay, 7 May 2014 00:47:01 UTC+1, Diggory Blake  wrote:<blockquote class=3D"gm=
ail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc soli=
d;padding-left: 1ex;"><div dir=3D"ltr">Interesting, I came up with this bas=
ed on that idea:<br><br><span style=3D"font-family:courier new,monospace">s=
truct memoize {<br>&nbsp;&nbsp; template&lt;typename=20
T&gt; memoized&lt;T&gt; operator()(T functor) { /* return a callable object
 which caches calls to the functor */ }<br>};<br><br>template&lt;typename T=
, typename U&gt; auto bind_modifier(U functor) {<br>&nbsp;&nbsp; T modifier=
;<br>&nbsp;&nbsp; return std::bind(functor, modifier(functor));<br>}<br><br=
>auto f =3D bind_modifier&lt;memoize&gt;([](<wbr>auto&amp; f, int a) {<br>&=
nbsp;&nbsp; return a &gt; 1 ? f(f, a-1) + f(f, a-2) : a;<br>});</span><br><=
br>I really like the syntax here as it means you can change the modifiers w=
ithout altering the lambda code. The only bit I'm concerned about is whethe=
r the compiler would be able to optimise away the extra parameter.<br><br>O=
n Tuesday, 6 May 2014 20:56:05 UTC+1, Alex B  wrote:<blockquote class=3D"gm=
ail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;p=
adding-left:1ex"><div dir=3D"ltr"><div>For the record, here is a small (not=
 so elegant) workaround using generic lambdas:</div><div>&nbsp;</div><div><=
div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;backgro=
und-color:rgb(250,250,250)"><code><div><span style=3D"color:rgb(0,0,136)">a=
uto</span><span style=3D"color:rgb(0,0,0)"> f </span><span style=3D"color:r=
gb(102,102,0)">=3D</span><span style=3D"color:rgb(0,0,0)"> </span><span sty=
le=3D"color:rgb(102,102,0)">[](</span><span style=3D"color:rgb(0,0,136)">in=
t</span><span style=3D"color:rgb(0,0,0)"> a</span><span style=3D"color:rgb(=
102,102,0)">)</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=
=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,0,0)"><br>&nbs=
p; &nbsp; </span><span style=3D"color:rgb(0,0,136)">auto</span><span style=
=3D"color:rgb(0,0,0)"> f2 </span><span style=3D"color:rgb(102,102,0)">=3D</=
span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,=
102,0)">[](</span><span style=3D"color:rgb(0,0,136)">int</span><span style=
=3D"color:rgb(0,0,0)"> a</span><span style=3D"color:rgb(102,102,0)">,</span=
><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)=
">auto</span><span style=3D"color:rgb(0,0,0)"> f2</span><span style=3D"colo=
r:rgb(102,102,0)">)</span><span style=3D"color:rgb(0,0,0)"><br>&nbsp; &nbsp=
; </span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:=
rgb(0,0,0)"><br>&nbsp; &nbsp; &nbsp; &nbsp; </span><span style=3D"color:rgb=
(0,0,136)">if</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D=
"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">a </span><s=
pan style=3D"color:rgb(102,102,0)">=3D=3D</span><span style=3D"color:rgb(0,=
0,0)"> </span><span style=3D"color:rgb(0,102,102)">0</span><span style=3D"c=
olor:rgb(102,102,0)">)</span><span style=3D"color:rgb(0,0,0)"><br>&nbsp; &n=
bsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style=3D"color:rgb(0,0,136)">=
return</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:=
rgb(0,102,102)">0</span><span style=3D"color:rgb(102,102,0)">;</span><span =
style=3D"color:rgb(0,0,0)"><br>&nbsp; &nbsp; &nbsp; &nbsp; </span><span sty=
le=3D"color:rgb(0,0,136)">else</span><span style=3D"color:rgb(0,0,0)"><br>&=
nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style=3D"color:rgb(0,=
0,136)">return</span><span style=3D"color:rgb(0,0,0)"> f2</span><span style=
=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">a</span>=
<span style=3D"color:rgb(102,102,0)">-</span><span style=3D"color:rgb(0,102=
,102)">1</span><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"=
color:rgb(0,0,0)"> f2</span><span style=3D"color:rgb(102,102,0)">);</span><=
span style=3D"color:rgb(0,0,0)"><br>&nbsp; &nbsp; </span><span style=3D"col=
or:rgb(102,102,0)">};</span><span style=3D"color:rgb(0,0,0)"><br>&nbsp; &nb=
sp; f2</span><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"co=
lor:rgb(0,0,0)">a</span><span style=3D"color:rgb(102,102,0)">,</span><span =
style=3D"color:rgb(0,0,0)"> f2</span><span style=3D"color:rgb(102,102,0)">)=
;</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rg=
b(102,102,0)">};</span></div></code></div><br></div><div><br>On Tuesday, Ma=
y 6, 2014 2:08:12 PM UTC-4, Diggory Blake wrote:</div><blockquote class=3D"=
gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left=
-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid"><div=
 dir=3D"ltr">Apologies if this has already been addressed somewhere:<br><br=
>When declaring a lambda, the type of the lambda is not available until aft=
er the body of the lambda has been compiled:<br><br><span style=3D"font-fam=
ily:courier new,monospace">auto f =3D [&amp;](int a){<br>&nbsp;&nbsp; if (a=
 =3D=3D 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>&nbsp;&nbsp; else=
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return f(a-1)+1; // This will fail: the =
type of 'f' is not yet known, so it cannot be bound to the lambda<br>};</sp=
an><br><br>This is understandable, and in this case without a significantly=
 smarter compiler is impossible to avoid (AFAIK). To make a recursive lambd=
a, you therefore have to wrap it in a std::function:<br><br><span style=3D"=
font-family:courier new,monospace">std::function&lt;int(int)&gt; f =3D  [&a=
mp;](int a){<br>&nbsp;&nbsp; if (a =3D=3D 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nb=
sp; return 0;<br>&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return=
 f(a-1)+1; // This will work: the type of 'f' is already known, as it does =
not depend on the type of the lambda<br>};</span><br><br>This obviously is =
much less efficient, and when tested, compilers were unable to optimise awa=
y the indirect call.<br><br>It seems like there should be a special case wh=
ere the compiler can determine the type of a lambda before compiling the la=
mbda body:<br><br><span style=3D"font-family:courier new,monospace">auto f =
=3D [&amp;f](int a) -&gt; int { // At the point of the capture list, the ty=
pe of 'f' is not fully defined, but is known to be a lambda (analogous to d=
eclaration of struct without body) and can therefore be bound by reference =
(but not value)<br>&nbsp;&nbsp; if (a =3D=3D 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;=
&nbsp; return 0;<br>&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret=
urn f(a-1)+1; // This should work: the type of the lambda was fully determi=
ned by the capture list, parameters and return type<br>};</span><br><br>Whe=
n the capture list, parameters and return type are all explicitly specified=
, then the type of the lambda should be known within the lambda body.<br><b=
r>Thoughts?<br></div></blockquote></div></blockquote></div></blockquote></d=
iv>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_1536_12544599.1399420229711--

.


Author: Diggory Blake <diggsey@googlemail.com>
Date: Tue, 6 May 2014 16:47:01 -0700 (PDT)
Raw View
------=_Part_2207_524142.1399420021744
Content-Type: text/plain; charset=UTF-8

Interesting, I came up with this based on that idea:

struct memoize {
   template<typename T> memoized<T> operator()(T functor) { /* return a
callable object which caches calls to the functor */ }
};

template<typename T, typename U> auto bind_modifier(U functor) {
   T modifier;
   return std::bind(functor, modifier(functor));
}

auto f = bind_modifier<memoize>([](auto& f, int a) {
   return a > 1 ? f(f, a-1) + f(f, a-2) : a;
});

I really like the syntax here as it means you can change the modifiers
without altering the lambda code. The only bit I'm concerned about is
whether the compiler would be able to optimise away the extra parameter.

On Tuesday, 6 May 2014 20:56:05 UTC+1, Alex B wrote:
>
> For the record, here is a small (not so elegant) workaround using generic
> lambdas:
>
> auto f = [](int a)
> {
>     auto f2 = [](int a, auto f2)
>     {
>         if (a == 0)
>             return 0;
>         else
>             return f2(a-1, f2);
>     };
>     f2(a, f2);
> };
>
>
> On Tuesday, May 6, 2014 2:08:12 PM UTC-4, Diggory Blake wrote:
>
>> Apologies if this has already been addressed somewhere:
>>
>> When declaring a lambda, the type of the lambda is not available until
>> after the body of the lambda has been compiled:
>>
>> auto f = [&](int a){
>>    if (a == 0)
>>       return 0;
>>    else
>>       return f(a-1)+1; // This will fail: the type of 'f' is not yet
>> known, so it cannot be bound to the lambda
>> };
>>
>> This is understandable, and in this case without a significantly smarter
>> compiler is impossible to avoid (AFAIK). To make a recursive lambda, you
>> therefore have to wrap it in a std::function:
>>
>> std::function<int(int)> f = [&](int a){
>>    if (a == 0)
>>       return 0;
>>    else
>>       return f(a-1)+1; // This will work: the type of 'f' is already
>> known, as it does not depend on the type of the lambda
>> };
>>
>> This obviously is much less efficient, and when tested, compilers were
>> unable to optimise away the indirect call.
>>
>> It seems like there should be a special case where the compiler can
>> determine the type of a lambda before compiling the lambda body:
>>
>> auto f = [&f](int a) -> int { // At the point of the capture list, the
>> type of 'f' is not fully defined, but is known to be a lambda (analogous to
>> declaration of struct without body) and can therefore be bound by reference
>> (but not value)
>>    if (a == 0)
>>       return 0;
>>    else
>>       return f(a-1)+1; // This should work: the type of the lambda was
>> fully determined by the capture list, parameters and return type
>> };
>>
>> When the capture list, parameters and return type are all explicitly
>> specified, then the type of the lambda should be known within the lambda
>> body.
>>
>> Thoughts?
>>
>

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_2207_524142.1399420021744
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Interesting, I came up with this based on that idea:<br><b=
r><span style=3D"font-family: courier new,monospace;">struct memoize {<br>&=
nbsp;&nbsp; template&lt;typename=20
T&gt; memoized&lt;T&gt; operator()(T functor) { /* return a callable object
 which caches calls to the functor */ }<br>};<br><br>template&lt;typename T=
, typename U&gt; auto bind_modifier(U functor) {<br>&nbsp;&nbsp; T modifier=
;<br>&nbsp;&nbsp; return std::bind(functor, modifier(functor));<br>}<br><br=
>auto f =3D bind_modifier&lt;memoize&gt;([](auto&amp; f, int a) {<br>&nbsp;=
&nbsp; return a &gt; 1 ? f(f, a-1) + f(f, a-2) : a;<br>});</span><br><br>I =
really like the syntax here as it means you can change the modifiers withou=
t altering the lambda code. The only bit I'm concerned about is whether the=
 compiler would be able to optimise away the extra parameter.<br><br>On Tue=
sday, 6 May 2014 20:56:05 UTC+1, Alex B  wrote:<blockquote class=3D"gmail_q=
uote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pad=
ding-left: 1ex;"><div dir=3D"ltr"><div>For the record, here is a small (not=
 so elegant) workaround using generic lambdas:</div><div>&nbsp;</div><div><=
div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;backgro=
und-color:rgb(250,250,250)"><code><div><span style=3D"color:rgb(0,0,136)">a=
uto</span><span style=3D"color:rgb(0,0,0)"> f </span><span style=3D"color:r=
gb(102,102,0)">=3D</span><span style=3D"color:rgb(0,0,0)"> </span><span sty=
le=3D"color:rgb(102,102,0)">[](</span><span style=3D"color:rgb(0,0,136)">in=
t</span><span style=3D"color:rgb(0,0,0)"> a</span><span style=3D"color:rgb(=
102,102,0)">)</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=
=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,0,0)"><br>&nbs=
p; &nbsp; </span><span style=3D"color:rgb(0,0,136)">auto</span><span style=
=3D"color:rgb(0,0,0)"> f2 </span><span style=3D"color:rgb(102,102,0)">=3D</=
span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,=
102,0)">[](</span><span style=3D"color:rgb(0,0,136)">int</span><span style=
=3D"color:rgb(0,0,0)"> a</span><span style=3D"color:rgb(102,102,0)">,</span=
><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)=
">auto</span><span style=3D"color:rgb(0,0,0)"> f2</span><span style=3D"colo=
r:rgb(102,102,0)">)</span><span style=3D"color:rgb(0,0,0)"><br>&nbsp; &nbsp=
; </span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:=
rgb(0,0,0)"><br>&nbsp; &nbsp; &nbsp; &nbsp; </span><span style=3D"color:rgb=
(0,0,136)">if</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D=
"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">a </span><s=
pan style=3D"color:rgb(102,102,0)">=3D=3D</span><span style=3D"color:rgb(0,=
0,0)"> </span><span style=3D"color:rgb(0,102,102)">0</span><span style=3D"c=
olor:rgb(102,102,0)">)</span><span style=3D"color:rgb(0,0,0)"><br>&nbsp; &n=
bsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style=3D"color:rgb(0,0,136)">=
return</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:=
rgb(0,102,102)">0</span><span style=3D"color:rgb(102,102,0)">;</span><span =
style=3D"color:rgb(0,0,0)"><br>&nbsp; &nbsp; &nbsp; &nbsp; </span><span sty=
le=3D"color:rgb(0,0,136)">else</span><span style=3D"color:rgb(0,0,0)"><br>&=
nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style=3D"color:rgb(0,=
0,136)">return</span><span style=3D"color:rgb(0,0,0)"> f2</span><span style=
=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">a</span>=
<span style=3D"color:rgb(102,102,0)">-</span><span style=3D"color:rgb(0,102=
,102)">1</span><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"=
color:rgb(0,0,0)"> f2</span><span style=3D"color:rgb(102,102,0)">);</span><=
span style=3D"color:rgb(0,0,0)"><br>&nbsp; &nbsp; </span><span style=3D"col=
or:rgb(102,102,0)">};</span><span style=3D"color:rgb(0,0,0)"><br>&nbsp; &nb=
sp; f2</span><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"co=
lor:rgb(0,0,0)">a</span><span style=3D"color:rgb(102,102,0)">,</span><span =
style=3D"color:rgb(0,0,0)"> f2</span><span style=3D"color:rgb(102,102,0)">)=
;</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rg=
b(102,102,0)">};</span></div></code></div><br></div><div><br>On Tuesday, Ma=
y 6, 2014 2:08:12 PM UTC-4, Diggory Blake wrote:</div><blockquote class=3D"=
gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left=
-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid"><div=
 dir=3D"ltr">Apologies if this has already been addressed somewhere:<br><br=
>When declaring a lambda, the type of the lambda is not available until aft=
er the body of the lambda has been compiled:<br><br><span style=3D"font-fam=
ily:courier new,monospace">auto f =3D [&amp;](int a){<br>&nbsp;&nbsp; if (a=
 =3D=3D 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>&nbsp;&nbsp; else=
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return f(a-1)+1; // This will fail: the =
type of 'f' is not yet known, so it cannot be bound to the lambda<br>};</sp=
an><br><br>This is understandable, and in this case without a significantly=
 smarter compiler is impossible to avoid (AFAIK). To make a recursive lambd=
a, you therefore have to wrap it in a std::function:<br><br><span style=3D"=
font-family:courier new,monospace">std::function&lt;int(int)&gt; f =3D  [&a=
mp;](int a){<br>&nbsp;&nbsp; if (a =3D=3D 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nb=
sp; return 0;<br>&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return=
 f(a-1)+1; // This will work: the type of 'f' is already known, as it does =
not depend on the type of the lambda<br>};</span><br><br>This obviously is =
much less efficient, and when tested, compilers were unable to optimise awa=
y the indirect call.<br><br>It seems like there should be a special case wh=
ere the compiler can determine the type of a lambda before compiling the la=
mbda body:<br><br><span style=3D"font-family:courier new,monospace">auto f =
=3D [&amp;f](int a) -&gt; int { // At the point of the capture list, the ty=
pe of 'f' is not fully defined, but is known to be a lambda (analogous to d=
eclaration of struct without body) and can therefore be bound by reference =
(but not value)<br>&nbsp;&nbsp; if (a =3D=3D 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;=
&nbsp; return 0;<br>&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret=
urn f(a-1)+1; // This should work: the type of the lambda was fully determi=
ned by the capture list, parameters and return type<br>};</span><br><br>Whe=
n the capture list, parameters and return type are all explicitly specified=
, then the type of the lambda should be known within the lambda body.<br><b=
r>Thoughts?<br></div></blockquote></div></blockquote></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_2207_524142.1399420021744--

.


Author: Richard Smith <richard@metafoo.co.uk>
Date: Tue, 6 May 2014 17:25:59 -0700
Raw View
--089e013d0502a89e3c04f8c468fd
Content-Type: text/plain; charset=UTF-8

#include <utility>
template<typename F> struct fixed_point {
  F f;
  template<typename ...P> decltype(auto) operator()(P &&...p) {
    return f(*this, std::forward<P>(p)...);
  }
};
template<typename F> fixed_point<F> fix(F &&f) { return { f }; }

auto fib = fix([](auto &fib, int n) -> int { return n > 2 ? fib(n-1) +
fib(n-2) : n; });
int main() { return fib(5); }

On Tue, May 6, 2014 at 4:50 PM, Diggory Blake <diggsey@googlemail.com>wrote:

> Correction, that should be:
> template<typename T, typename U> auto bind_modifier(U functor) {
>    T modifier;
>    return std::bind(modifier(functor), modifier(functor));
> }
>
> And the modifier would have to be aware of the extra first parameter.
>
>
> On Wednesday, 7 May 2014 00:47:01 UTC+1, Diggory Blake wrote:
>>
>> Interesting, I came up with this based on that idea:
>>
>> struct memoize {
>>    template<typename T> memoized<T> operator()(T functor) { /* return a
>> callable object which caches calls to the functor */ }
>> };
>>
>> template<typename T, typename U> auto bind_modifier(U functor) {
>>    T modifier;
>>    return std::bind(functor, modifier(functor));
>> }
>>
>> auto f = bind_modifier<memoize>([](auto& f, int a) {
>>    return a > 1 ? f(f, a-1) + f(f, a-2) : a;
>> });
>>
>> I really like the syntax here as it means you can change the modifiers
>> without altering the lambda code. The only bit I'm concerned about is
>> whether the compiler would be able to optimise away the extra parameter.
>>
>> On Tuesday, 6 May 2014 20:56:05 UTC+1, Alex B wrote:
>>>
>>> For the record, here is a small (not so elegant) workaround using
>>> generic lambdas:
>>>
>>> auto f = [](int a)
>>> {
>>>     auto f2 = [](int a, auto f2)
>>>     {
>>>         if (a == 0)
>>>             return 0;
>>>         else
>>>             return f2(a-1, f2);
>>>     };
>>>     f2(a, f2);
>>> };
>>>
>>>
>>> On Tuesday, May 6, 2014 2:08:12 PM UTC-4, Diggory Blake wrote:
>>>
>>>> Apologies if this has already been addressed somewhere:
>>>>
>>>> When declaring a lambda, the type of the lambda is not available until
>>>> after the body of the lambda has been compiled:
>>>>
>>>> auto f = [&](int a){
>>>>    if (a == 0)
>>>>       return 0;
>>>>    else
>>>>       return f(a-1)+1; // This will fail: the type of 'f' is not yet
>>>> known, so it cannot be bound to the lambda
>>>> };
>>>>
>>>> This is understandable, and in this case without a significantly
>>>> smarter compiler is impossible to avoid (AFAIK). To make a recursive
>>>> lambda, you therefore have to wrap it in a std::function:
>>>>
>>>> std::function<int(int)> f = [&](int a){
>>>>    if (a == 0)
>>>>       return 0;
>>>>    else
>>>>       return f(a-1)+1; // This will work: the type of 'f' is already
>>>> known, as it does not depend on the type of the lambda
>>>> };
>>>>
>>>> This obviously is much less efficient, and when tested, compilers were
>>>> unable to optimise away the indirect call.
>>>>
>>>> It seems like there should be a special case where the compiler can
>>>> determine the type of a lambda before compiling the lambda body:
>>>>
>>>> auto f = [&f](int a) -> int { // At the point of the capture list, the
>>>> type of 'f' is not fully defined, but is known to be a lambda (analogous to
>>>> declaration of struct without body) and can therefore be bound by reference
>>>> (but not value)
>>>>    if (a == 0)
>>>>       return 0;
>>>>    else
>>>>       return f(a-1)+1; // This should work: the type of the lambda was
>>>> fully determined by the capture list, parameters and return type
>>>> };
>>>>
>>>> When the capture list, parameters and return type are all explicitly
>>>> specified, then the type of the lambda should be known within the lambda
>>>> body.
>>>>
>>>> Thoughts?
>>>>
>>>  --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

--089e013d0502a89e3c04f8c468fd
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div><font face=3D"courier new, monospace">#include &lt;ut=
ility&gt;<br></font></div><div><font face=3D"courier new, monospace">templa=
te&lt;typename F&gt; struct fixed_point {</font></div><div><font face=3D"co=
urier new, monospace">=C2=A0 F f;</font></div>
<div><font face=3D"courier new, monospace">=C2=A0 template&lt;typename ...P=
&gt; decltype(auto) operator()(P &amp;&amp;...p) {</font></div><div><font f=
ace=3D"courier new, monospace">=C2=A0 =C2=A0 return f(*this, std::forward&l=
t;P&gt;(p)...);</font></div>
<div><font face=3D"courier new, monospace">=C2=A0 }</font></div><div><font =
face=3D"courier new, monospace">};</font></div><div><font face=3D"courier n=
ew, monospace">template&lt;typename F&gt; fixed_point&lt;F&gt; fix(F &amp;&=
amp;f) { return { f }; }</font></div>
<div><font face=3D"courier new, monospace"><br></font></div><div><font face=
=3D"courier new, monospace">auto fib =3D fix([](auto &amp;fib, int n) -&gt;=
 int { return n &gt; 2 ? fib(n-1) + fib(n-2) : n; });</font></div><div><fon=
t face=3D"courier new, monospace">int main() { return fib(5); }</font></div=
>
<div class=3D"gmail_extra"><br><div class=3D"gmail_quote">On Tue, May 6, 20=
14 at 4:50 PM, Diggory Blake <span dir=3D"ltr">&lt;<a href=3D"mailto:diggse=
y@googlemail.com" target=3D"_blank">diggsey@googlemail.com</a>&gt;</span> w=
rote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div dir=3D"ltr">Correction, that should be:=
<br><span style=3D"font-family:courier new,monospace"><div class=3D"">templ=
ate&lt;typename T, typename U&gt; auto bind_modifier(U functor) {<br>
=C2=A0=C2=A0 T modifier;<br></div>=C2=A0=C2=A0 return std::bind(modifier(fu=
nctor), modifier(functor));<br>}</span><br><br>And the modifier would have =
to be aware of the extra first parameter.<div><div class=3D"h5"><br><br>On =
Wednesday, 7 May 2014 00:47:01 UTC+1, Diggory Blake  wrote:<blockquote clas=
s=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc =
solid;padding-left:1ex">
<div dir=3D"ltr">Interesting, I came up with this based on that idea:<br><b=
r><span style=3D"font-family:courier new,monospace">struct memoize {<br>=C2=
=A0=C2=A0 template&lt;typename=20
T&gt; memoized&lt;T&gt; operator()(T functor) { /* return a callable object
 which caches calls to the functor */ }<br>};<br><br>template&lt;typename T=
, typename U&gt; auto bind_modifier(U functor) {<br>=C2=A0=C2=A0 T modifier=
;<br>=C2=A0=C2=A0 return std::bind(functor, modifier(functor));<br>}<br><br=
>auto f =3D bind_modifier&lt;memoize&gt;([](<u></u>auto&amp; f, int a) {<br=
>
=C2=A0=C2=A0 return a &gt; 1 ? f(f, a-1) + f(f, a-2) : a;<br>});</span><br>=
<br>I really like the syntax here as it means you can change the modifiers =
without altering the lambda code. The only bit I&#39;m concerned about is w=
hether the compiler would be able to optimise away the extra parameter.<br>
<br>On Tuesday, 6 May 2014 20:56:05 UTC+1, Alex B  wrote:<blockquote class=
=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr"><div>For the record, here is a smal=
l (not so elegant) workaround using generic lambdas:</div>
<div>=C2=A0</div><div><div style=3D"border:1px solid rgb(187,187,187);word-=
wrap:break-word;background-color:rgb(250,250,250)"><code><div><span style=
=3D"color:rgb(0,0,136)">auto</span><span style=3D"color:rgb(0,0,0)"> f </sp=
an><span style=3D"color:rgb(102,102,0)">=3D</span><span style=3D"color:rgb(=
0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">[](</span><span style=
=3D"color:rgb(0,0,136)">int</span><span style=3D"color:rgb(0,0,0)"> a</span=
><span style=3D"color:rgb(102,102,0)">)</span><span style=3D"color:rgb(0,0,=
0)"><br>
</span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rg=
b(0,0,0)"><br>=C2=A0 =C2=A0 </span><span style=3D"color:rgb(0,0,136)">auto<=
/span><span style=3D"color:rgb(0,0,0)"> f2 </span><span style=3D"color:rgb(=
102,102,0)">=3D</span><span style=3D"color:rgb(0,0,0)"> </span><span style=
=3D"color:rgb(102,102,0)">[](</span><span style=3D"color:rgb(0,0,136)">int<=
/span><span style=3D"color:rgb(0,0,0)"> a</span><span style=3D"color:rgb(10=
2,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"c=
olor:rgb(0,0,136)">auto</span><span style=3D"color:rgb(0,0,0)"> f2</span><s=
pan style=3D"color:rgb(102,102,0)">)</span><span style=3D"color:rgb(0,0,0)"=
><br>
=C2=A0 =C2=A0 </span><span style=3D"color:rgb(102,102,0)">{</span><span sty=
le=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=
=3D"color:rgb(0,0,136)">if</span><span style=3D"color:rgb(0,0,0)"> </span><=
span style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)=
">a </span><span style=3D"color:rgb(102,102,0)">=3D=3D</span><span style=3D=
"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">0</span><sp=
an style=3D"color:rgb(102,102,0)">)</span><span style=3D"color:rgb(0,0,0)">=
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:rgb(0=
,0,136)">return</span><span style=3D"color:rgb(0,0,0)"> </span><span style=
=3D"color:rgb(0,102,102)">0</span><span style=3D"color:rgb(102,102,0)">;</s=
pan><span style=3D"color:rgb(0,0,0)"><br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:rgb(0,0,136)">else<=
/span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 </span><span style=3D"color:rgb(0,0,136)">return</span><span sty=
le=3D"color:rgb(0,0,0)"> f2</span><span style=3D"color:rgb(102,102,0)">(</s=
pan><span style=3D"color:rgb(0,0,0)">a</span><span style=3D"color:rgb(102,1=
02,0)">-</span><span style=3D"color:rgb(0,102,102)">1</span><span style=3D"=
color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> f2</span><s=
pan style=3D"color:rgb(102,102,0)">);</span><span style=3D"color:rgb(0,0,0)=
"><br>
=C2=A0 =C2=A0 </span><span style=3D"color:rgb(102,102,0)">};</span><span st=
yle=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 f2</span><span style=3D"color:rg=
b(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">a</span><span style=
=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> f2</spa=
n><span style=3D"color:rgb(102,102,0)">);</span><span style=3D"color:rgb(0,=
0,0)"><br>
</span><span style=3D"color:rgb(102,102,0)">};</span></div></code></div><br=
></div><div><br>On Tuesday, May 6, 2014 2:08:12 PM UTC-4, Diggory Blake wro=
te:</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8e=
x;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px=
;border-left-style:solid">
<div dir=3D"ltr">Apologies if this has already been addressed somewhere:<br=
><br>When declaring a lambda, the type of the lambda is not available until=
 after the body of the lambda has been compiled:<br><br><span style=3D"font=
-family:courier new,monospace">auto f =3D [&amp;](int a){<br>
=C2=A0=C2=A0 if (a =3D=3D 0)<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return 0;<br=
>=C2=A0=C2=A0 else<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return f(a-1)+1; // Th=
is will fail: the type of &#39;f&#39; is not yet known, so it cannot be bou=
nd to the lambda<br>};</span><br><br>This is understandable, and in this ca=
se without a significantly smarter compiler is impossible to avoid (AFAIK).=
 To make a recursive lambda, you therefore have to wrap it in a std::functi=
on:<br>
<br><span style=3D"font-family:courier new,monospace">std::function&lt;int(=
int)&gt; f =3D  [&amp;](int a){<br>=C2=A0=C2=A0 if (a =3D=3D 0)<br>=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0 return 0;<br>=C2=A0=C2=A0 else<br>=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 return f(a-1)+1; // This will work: the type of &#39;f&#39;=
 is already known, as it does not depend on the type of the lambda<br>
};</span><br><br>This obviously is much less efficient, and when tested, co=
mpilers were unable to optimise away the indirect call.<br><br>It seems lik=
e there should be a special case where the compiler can determine the type =
of a lambda before compiling the lambda body:<br>
<br><span style=3D"font-family:courier new,monospace">auto f =3D [&amp;f](i=
nt a) -&gt; int { // At the point of the capture list, the type of &#39;f&#=
39; is not fully defined, but is known to be a lambda (analogous to declara=
tion of struct without body) and can therefore be bound by reference (but n=
ot value)<br>
=C2=A0=C2=A0 if (a =3D=3D 0)<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return 0;<br=
>=C2=A0=C2=A0 else<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return f(a-1)+1; // Th=
is should work: the type of the lambda was fully determined by the capture =
list, parameters and return type<br>};</span><br><br>When the capture list,=
 parameters and return type are all explicitly specified, then the type of =
the lambda should be known within the lambda body.<br>
<br>Thoughts?<br></div></blockquote></div></blockquote></div></blockquote><=
/div></div></div><div class=3D"HOEnZb"><div class=3D"h5">

<p></p>

-- <br>
<br>
--- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_=
blank">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--089e013d0502a89e3c04f8c468fd--

.


Author: inkwizytoryankes@gmail.com
Date: Wed, 7 May 2014 09:27:20 -0700 (PDT)
Raw View
------=_Part_2522_1247388.1399480040160
Content-Type: text/plain; charset=UTF-8

Is another solution for pure lambdas:

static int (*self)(int) = [](int i)->int { return i>0 ? self(i-1)*i : 1; };




On Tuesday, May 6, 2014 8:08:12 PM UTC+2, Diggory Blake wrote:
>
> Apologies if this has already been addressed somewhere:
>
> When declaring a lambda, the type of the lambda is not available until
> after the body of the lambda has been compiled:
>
> auto f = [&](int a){
>    if (a == 0)
>       return 0;
>    else
>       return f(a-1)+1; // This will fail: the type of 'f' is not yet
> known, so it cannot be bound to the lambda
> };
>
> This is understandable, and in this case without a significantly smarter
> compiler is impossible to avoid (AFAIK). To make a recursive lambda, you
> therefore have to wrap it in a std::function:
>
> std::function<int(int)> f = [&](int a){
>    if (a == 0)
>       return 0;
>    else
>       return f(a-1)+1; // This will work: the type of 'f' is already
> known, as it does not depend on the type of the lambda
> };
>
> This obviously is much less efficient, and when tested, compilers were
> unable to optimise away the indirect call.
>
> It seems like there should be a special case where the compiler can
> determine the type of a lambda before compiling the lambda body:
>
> auto f = [&f](int a) -> int { // At the point of the capture list, the
> type of 'f' is not fully defined, but is known to be a lambda (analogous to
> declaration of struct without body) and can therefore be bound by reference
> (but not value)
>    if (a == 0)
>       return 0;
>    else
>       return f(a-1)+1; // This should work: the type of the lambda was
> fully determined by the capture list, parameters and return type
> };
>
> When the capture list, parameters and return type are all explicitly
> specified, then the type of the lambda should be known within the lambda
> body.
>
> Thoughts?
>

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_2522_1247388.1399480040160
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Is another solution for pure lambdas:<br><div class=3D"pre=
ttyprint" style=3D"background-color: rgb(250, 250, 250); border-color: rgb(=
187, 187, 187); border-style: solid; border-width: 1px; word-wrap: break-wo=
rd;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><pre style=
=3D"" class=3D"lang-cpp prettyprint prettyprinted"><code><span style=3D"col=
or: #008;" class=3D"styled-by-prettify">static</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">int</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">(*</span><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">self</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)(<=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">int</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">[](</span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">int</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> i</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">)-&gt;</span><span style=3D"color: #008;" class=3D"styled-by-prettify">in=
t</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">return</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> i</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">&gt;</span><span style=3D"color: #066;" class=3D=
"styled-by-prettify">0</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">?</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </spa=
n><span style=3D"color: #008;" class=3D"styled-by-prettify">self</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">i</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">-</span><span style=3D"color: #066;" =
class=3D"styled-by-prettify">1</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">)*</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify">i </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">:</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #066;" class=3D"styled-by-prettify">1</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">};</span></code></pre></div></code></div>=
<br><br><br>On Tuesday, May 6, 2014 8:08:12 PM UTC+2, Diggory Blake wrote:<=
blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bord=
er-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">Apologies if t=
his has already been addressed somewhere:<br><br>When declaring a lambda, t=
he type of the lambda is not available until after the body of the lambda h=
as been compiled:<br><br><span style=3D"font-family:courier new,monospace">=
auto f =3D [&amp;](int a){<br>&nbsp;&nbsp; if (a =3D=3D 0)<br>&nbsp;&nbsp;&=
nbsp;&nbsp;&nbsp; return 0;<br>&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp=
;&nbsp; return f(a-1)+1; // This will fail: the type of 'f' is not yet know=
n, so it cannot be bound to the lambda<br>};</span><br><br>This is understa=
ndable, and in this case without a significantly smarter compiler is imposs=
ible to avoid (AFAIK). To make a recursive lambda, you therefore have to wr=
ap it in a std::function:<br><br><span style=3D"font-family:courier new,mon=
ospace">std::function&lt;int(int)&gt; f =3D  [&amp;](int a){<br>&nbsp;&nbsp=
; if (a =3D=3D 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>&nbsp;&nbs=
p; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return f(a-1)+1; // This will wor=
k: the type of 'f' is already known, as it does not depend on the type of t=
he lambda<br>};</span><br><br>This obviously is much less efficient, and wh=
en tested, compilers were unable to optimise away the indirect call.<br><br=
>It seems like there should be a special case where the compiler can determ=
ine the type of a lambda before compiling the lambda body:<br><br><span sty=
le=3D"font-family:courier new,monospace">auto f =3D [&amp;f](int a) -&gt; i=
nt { // At the point of the capture list, the type of 'f' is not fully defi=
ned, but is known to be a lambda (analogous to declaration of struct withou=
t body) and can therefore be bound by reference (but not value)<br>&nbsp;&n=
bsp; if (a =3D=3D 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>&nbsp;&=
nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return f(a-1)+1; // This shoul=
d work: the type of the lambda was fully determined by the capture list, pa=
rameters and return type<br>};</span><br><br>When the capture list, paramet=
ers and return type are all explicitly specified, then the type of the lamb=
da should be known within the lambda body.<br><br>Thoughts?<br></div></bloc=
kquote></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_2522_1247388.1399480040160--

.


Author: Alex B <devalexb@gmail.com>
Date: Wed, 7 May 2014 12:30:51 -0400
Raw View
--001a11c377d644bf6404f8d1e31f
Content-Type: text/plain; charset=UTF-8

Very interesting library solution...


On Tue, May 6, 2014 at 8:25 PM, Richard Smith <richard@metafoo.co.uk> wrote:

> #include <utility>
> template<typename F> struct fixed_point {
>   F f;
>   template<typename ...P> decltype(auto) operator()(P &&...p) {
>     return f(*this, std::forward<P>(p)...);
>   }
> };
> template<typename F> fixed_point<F> fix(F &&f) { return { f }; }
>
> auto fib = fix([](auto &fib, int n) -> int { return n > 2 ? fib(n-1) +
> fib(n-2) : n; });
> int main() { return fib(5); }
>
> On Tue, May 6, 2014 at 4:50 PM, Diggory Blake <diggsey@googlemail.com>wrote:
>
>> Correction, that should be:
>> template<typename T, typename U> auto bind_modifier(U functor) {
>>    T modifier;
>>    return std::bind(modifier(functor), modifier(functor));
>> }
>>
>> And the modifier would have to be aware of the extra first parameter.
>>
>>
>> On Wednesday, 7 May 2014 00:47:01 UTC+1, Diggory Blake wrote:
>>>
>>> Interesting, I came up with this based on that idea:
>>>
>>> struct memoize {
>>>    template<typename T> memoized<T> operator()(T functor) { /* return a
>>> callable object which caches calls to the functor */ }
>>> };
>>>
>>> template<typename T, typename U> auto bind_modifier(U functor) {
>>>    T modifier;
>>>    return std::bind(functor, modifier(functor));
>>> }
>>>
>>> auto f = bind_modifier<memoize>([](auto& f, int a) {
>>>    return a > 1 ? f(f, a-1) + f(f, a-2) : a;
>>> });
>>>
>>> I really like the syntax here as it means you can change the modifiers
>>> without altering the lambda code. The only bit I'm concerned about is
>>> whether the compiler would be able to optimise away the extra parameter.
>>>
>>> On Tuesday, 6 May 2014 20:56:05 UTC+1, Alex B wrote:
>>>>
>>>> For the record, here is a small (not so elegant) workaround using
>>>> generic lambdas:
>>>>
>>>> auto f = [](int a)
>>>> {
>>>>     auto f2 = [](int a, auto f2)
>>>>     {
>>>>         if (a == 0)
>>>>             return 0;
>>>>         else
>>>>             return f2(a-1, f2);
>>>>     };
>>>>     f2(a, f2);
>>>> };
>>>>
>>>>
>>>> On Tuesday, May 6, 2014 2:08:12 PM UTC-4, Diggory Blake wrote:
>>>>
>>>>> Apologies if this has already been addressed somewhere:
>>>>>
>>>>> When declaring a lambda, the type of the lambda is not available until
>>>>> after the body of the lambda has been compiled:
>>>>>
>>>>> auto f = [&](int a){
>>>>>    if (a == 0)
>>>>>       return 0;
>>>>>    else
>>>>>       return f(a-1)+1; // This will fail: the type of 'f' is not yet
>>>>> known, so it cannot be bound to the lambda
>>>>> };
>>>>>
>>>>> This is understandable, and in this case without a significantly
>>>>> smarter compiler is impossible to avoid (AFAIK). To make a recursive
>>>>> lambda, you therefore have to wrap it in a std::function:
>>>>>
>>>>> std::function<int(int)> f = [&](int a){
>>>>>    if (a == 0)
>>>>>       return 0;
>>>>>    else
>>>>>       return f(a-1)+1; // This will work: the type of 'f' is already
>>>>> known, as it does not depend on the type of the lambda
>>>>> };
>>>>>
>>>>> This obviously is much less efficient, and when tested, compilers were
>>>>> unable to optimise away the indirect call.
>>>>>
>>>>> It seems like there should be a special case where the compiler can
>>>>> determine the type of a lambda before compiling the lambda body:
>>>>>
>>>>> auto f = [&f](int a) -> int { // At the point of the capture list, the
>>>>> type of 'f' is not fully defined, but is known to be a lambda (analogous to
>>>>> declaration of struct without body) and can therefore be bound by reference
>>>>> (but not value)
>>>>>    if (a == 0)
>>>>>       return 0;
>>>>>    else
>>>>>       return f(a-1)+1; // This should work: the type of the lambda was
>>>>> fully determined by the capture list, parameters and return type
>>>>> };
>>>>>
>>>>> When the capture list, parameters and return type are all explicitly
>>>>> specified, then the type of the lambda should be known within the lambda
>>>>> body.
>>>>>
>>>>> Thoughts?
>>>>>
>>>>  --
>>
>> ---
>> You received this message because you are subscribed to the Google Groups
>> "ISO C++ Standard - Future Proposals" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to std-proposals+unsubscribe@isocpp.org.
>>
>> To post to this group, send email to std-proposals@isocpp.org.
>> Visit this group at
>> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>>
>
>  --
>
> ---
> You received this message because you are subscribed to a topic in the
> Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/a/isocpp.org/d/topic/std-proposals/bcBoAn226v8/unsubscribe
> .
> To unsubscribe from this group and all its topics, send an email to
> std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

--001a11c377d644bf6404f8d1e31f
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Very interesting library solution...<div class=3D"gmail_ex=
tra"><br><br><div class=3D"gmail_quote">On Tue, May 6, 2014 at 8:25 PM, Ric=
hard Smith <span dir=3D"ltr">&lt;<a href=3D"mailto:richard@metafoo.co.uk" t=
arget=3D"_blank">richard@metafoo.co.uk</a>&gt;</span> wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><font face=3D"courier =
new, monospace">#include &lt;utility&gt;<br></font></div><div><font face=3D=
"courier new, monospace">template&lt;typename F&gt; struct fixed_point {</f=
ont></div>
<div><font face=3D"courier new, monospace">=C2=A0 F f;</font></div>
<div><font face=3D"courier new, monospace">=C2=A0 template&lt;typename ...P=
&gt; decltype(auto) operator()(P &amp;&amp;...p) {</font></div><div><font f=
ace=3D"courier new, monospace">=C2=A0 =C2=A0 return f(*this, std::forward&l=
t;P&gt;(p)...);</font></div>

<div><font face=3D"courier new, monospace">=C2=A0 }</font></div><div><font =
face=3D"courier new, monospace">};</font></div><div><font face=3D"courier n=
ew, monospace">template&lt;typename F&gt; fixed_point&lt;F&gt; fix(F &amp;&=
amp;f) { return { f }; }</font></div>

<div><font face=3D"courier new, monospace"><br></font></div><div><font face=
=3D"courier new, monospace">auto fib =3D fix([](auto &amp;fib, int n) -&gt;=
 int { return n &gt; 2 ? fib(n-1) + fib(n-2) : n; });</font></div><div><fon=
t face=3D"courier new, monospace">int main() { return fib(5); }</font></div=
>

<div class=3D"gmail_extra"><br><div class=3D"gmail_quote"><div><div class=
=3D"h5">On Tue, May 6, 2014 at 4:50 PM, Diggory Blake <span dir=3D"ltr">&lt=
;<a href=3D"mailto:diggsey@googlemail.com" target=3D"_blank">diggsey@google=
mail.com</a>&gt;</span> wrote:<br>

</div></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bo=
rder-left:1px #ccc solid;padding-left:1ex"><div><div class=3D"h5"><div dir=
=3D"ltr">Correction, that should be:<br><span style=3D"font-family:courier =
new,monospace"><div>
template&lt;typename T, typename U&gt; auto bind_modifier(U functor) {<br>
=C2=A0=C2=A0 T modifier;<br></div>=C2=A0=C2=A0 return std::bind(modifier(fu=
nctor), modifier(functor));<br>}</span><br><br>And the modifier would have =
to be aware of the extra first parameter.<div><div><br><br>On Wednesday, 7 =
May 2014 00:47:01 UTC+1, Diggory Blake  wrote:<blockquote class=3D"gmail_qu=
ote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding=
-left:1ex">

<div dir=3D"ltr">Interesting, I came up with this based on that idea:<br><b=
r><span style=3D"font-family:courier new,monospace">struct memoize {<br>=C2=
=A0=C2=A0 template&lt;typename=20
T&gt; memoized&lt;T&gt; operator()(T functor) { /* return a callable object
 which caches calls to the functor */ }<br>};<br><br>template&lt;typename T=
, typename U&gt; auto bind_modifier(U functor) {<br>=C2=A0=C2=A0 T modifier=
;<br>=C2=A0=C2=A0 return std::bind(functor, modifier(functor));<br>}<br><br=
>auto f =3D bind_modifier&lt;memoize&gt;([](<u></u>auto&amp; f, int a) {<br=
>

=C2=A0=C2=A0 return a &gt; 1 ? f(f, a-1) + f(f, a-2) : a;<br>});</span><br>=
<br>I really like the syntax here as it means you can change the modifiers =
without altering the lambda code. The only bit I&#39;m concerned about is w=
hether the compiler would be able to optimise away the extra parameter.<br>

<br>On Tuesday, 6 May 2014 20:56:05 UTC+1, Alex B  wrote:<blockquote class=
=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr"><div>For the record, here is a smal=
l (not so elegant) workaround using generic lambdas:</div>

<div>=C2=A0</div><div><div style=3D"border:1px solid rgb(187,187,187);word-=
wrap:break-word;background-color:rgb(250,250,250)"><code><div><span style=
=3D"color:rgb(0,0,136)">auto</span><span style=3D"color:rgb(0,0,0)"> f </sp=
an><span style=3D"color:rgb(102,102,0)">=3D</span><span style=3D"color:rgb(=
0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">[](</span><span style=
=3D"color:rgb(0,0,136)">int</span><span style=3D"color:rgb(0,0,0)"> a</span=
><span style=3D"color:rgb(102,102,0)">)</span><span style=3D"color:rgb(0,0,=
0)"><br>

</span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rg=
b(0,0,0)"><br>=C2=A0 =C2=A0 </span><span style=3D"color:rgb(0,0,136)">auto<=
/span><span style=3D"color:rgb(0,0,0)"> f2 </span><span style=3D"color:rgb(=
102,102,0)">=3D</span><span style=3D"color:rgb(0,0,0)"> </span><span style=
=3D"color:rgb(102,102,0)">[](</span><span style=3D"color:rgb(0,0,136)">int<=
/span><span style=3D"color:rgb(0,0,0)"> a</span><span style=3D"color:rgb(10=
2,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"c=
olor:rgb(0,0,136)">auto</span><span style=3D"color:rgb(0,0,0)"> f2</span><s=
pan style=3D"color:rgb(102,102,0)">)</span><span style=3D"color:rgb(0,0,0)"=
><br>

=C2=A0 =C2=A0 </span><span style=3D"color:rgb(102,102,0)">{</span><span sty=
le=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=
=3D"color:rgb(0,0,136)">if</span><span style=3D"color:rgb(0,0,0)"> </span><=
span style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)=
">a </span><span style=3D"color:rgb(102,102,0)">=3D=3D</span><span style=3D=
"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">0</span><sp=
an style=3D"color:rgb(102,102,0)">)</span><span style=3D"color:rgb(0,0,0)">=
<br>

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:rgb(0=
,0,136)">return</span><span style=3D"color:rgb(0,0,0)"> </span><span style=
=3D"color:rgb(0,102,102)">0</span><span style=3D"color:rgb(102,102,0)">;</s=
pan><span style=3D"color:rgb(0,0,0)"><br>

=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:rgb(0,0,136)">else<=
/span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 </span><span style=3D"color:rgb(0,0,136)">return</span><span sty=
le=3D"color:rgb(0,0,0)"> f2</span><span style=3D"color:rgb(102,102,0)">(</s=
pan><span style=3D"color:rgb(0,0,0)">a</span><span style=3D"color:rgb(102,1=
02,0)">-</span><span style=3D"color:rgb(0,102,102)">1</span><span style=3D"=
color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> f2</span><s=
pan style=3D"color:rgb(102,102,0)">);</span><span style=3D"color:rgb(0,0,0)=
"><br>

=C2=A0 =C2=A0 </span><span style=3D"color:rgb(102,102,0)">};</span><span st=
yle=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 f2</span><span style=3D"color:rg=
b(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">a</span><span style=
=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> f2</spa=
n><span style=3D"color:rgb(102,102,0)">);</span><span style=3D"color:rgb(0,=
0,0)"><br>

</span><span style=3D"color:rgb(102,102,0)">};</span></div></code></div><br=
></div><div><br>On Tuesday, May 6, 2014 2:08:12 PM UTC-4, Diggory Blake wro=
te:</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8e=
x;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px=
;border-left-style:solid">

<div dir=3D"ltr">Apologies if this has already been addressed somewhere:<br=
><br>When declaring a lambda, the type of the lambda is not available until=
 after the body of the lambda has been compiled:<br><br><span style=3D"font=
-family:courier new,monospace">auto f =3D [&amp;](int a){<br>

=C2=A0=C2=A0 if (a =3D=3D 0)<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return 0;<br=
>=C2=A0=C2=A0 else<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return f(a-1)+1; // Th=
is will fail: the type of &#39;f&#39; is not yet known, so it cannot be bou=
nd to the lambda<br>};</span><br><br>This is understandable, and in this ca=
se without a significantly smarter compiler is impossible to avoid (AFAIK).=
 To make a recursive lambda, you therefore have to wrap it in a std::functi=
on:<br>

<br><span style=3D"font-family:courier new,monospace">std::function&lt;int(=
int)&gt; f =3D  [&amp;](int a){<br>=C2=A0=C2=A0 if (a =3D=3D 0)<br>=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0 return 0;<br>=C2=A0=C2=A0 else<br>=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 return f(a-1)+1; // This will work: the type of &#39;f&#39;=
 is already known, as it does not depend on the type of the lambda<br>

};</span><br><br>This obviously is much less efficient, and when tested, co=
mpilers were unable to optimise away the indirect call.<br><br>It seems lik=
e there should be a special case where the compiler can determine the type =
of a lambda before compiling the lambda body:<br>

<br><span style=3D"font-family:courier new,monospace">auto f =3D [&amp;f](i=
nt a) -&gt; int { // At the point of the capture list, the type of &#39;f&#=
39; is not fully defined, but is known to be a lambda (analogous to declara=
tion of struct without body) and can therefore be bound by reference (but n=
ot value)<br>

=C2=A0=C2=A0 if (a =3D=3D 0)<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return 0;<br=
>=C2=A0=C2=A0 else<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return f(a-1)+1; // Th=
is should work: the type of the lambda was fully determined by the capture =
list, parameters and return type<br>};</span><br><br>When the capture list,=
 parameters and return type are all explicitly specified, then the type of =
the lambda should be known within the lambda body.<br>

<br>Thoughts?<br></div></blockquote></div></blockquote></div></blockquote><=
/div></div></div></div></div><div><div><span class=3D"HOEnZb"><font color=
=3D"#888888">

<p></p>

-- <br>
<br>
--- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_=
blank">std-proposals+unsubscribe@isocpp.org</a>.</font></span><div class=3D=
"">
<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></div></blockquote></div><br></div></div><div class=3D"HOEnZb">=
<div class=3D"h5">

<p></p>

-- <br>
<br>
--- <br>
You received this message because you are subscribed to a topic in the Goog=
le Groups &quot;ISO C++ Standard - Future Proposals&quot; group.<br>
To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/=
a/isocpp.org/d/topic/std-proposals/bcBoAn226v8/unsubscribe" target=3D"_blan=
k">https://groups.google.com/a/isocpp.org/d/topic/std-proposals/bcBoAn226v8=
/unsubscribe</a>.<br>

To unsubscribe from this group and all its topics, send an email to <a href=
=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_blank">std-prop=
osals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--001a11c377d644bf6404f8d1e31f--

.


Author: Diggory Blake <diggsey@googlemail.com>
Date: Wed, 7 May 2014 16:35:26 -0700 (PDT)
Raw View
------=_Part_22_4332753.1399505726795
Content-Type: text/plain; charset=UTF-8

Took it a little further and got something that allows any number of
modifiers to be applied without changing the lambda:

    auto f = bind_modifiers([](auto& f, int i) -> int {
        return (i < 2) ? i : f(i-2) + f(i-1);
    }, memoize());

You can also supply arguments to modifiers:

    auto f = bind_modifiers([](auto& f, int i) -> int {
        return (i < 2) ? i : f(i-2) + f(i-1);
    }, trace("You just called 'f'"), memoize());

And zero modifiers will work too (ie. you won't have to supply the special
first argument).

On Wednesday, 7 May 2014 17:30:51 UTC+1, Alex B wrote:
>
> Very interesting library solution...
>
>
> On Tue, May 6, 2014 at 8:25 PM, Richard Smith <ric...@metafoo.co.uk<javascript:>
> > wrote:
>
>> #include <utility>
>> template<typename F> struct fixed_point {
>>   F f;
>>   template<typename ...P> decltype(auto) operator()(P &&...p) {
>>     return f(*this, std::forward<P>(p)...);
>>   }
>> };
>> template<typename F> fixed_point<F> fix(F &&f) { return { f }; }
>>
>> auto fib = fix([](auto &fib, int n) -> int { return n > 2 ? fib(n-1) +
>> fib(n-2) : n; });
>> int main() { return fib(5); }
>>
>> On Tue, May 6, 2014 at 4:50 PM, Diggory Blake <dig...@googlemail.com<javascript:>
>> > wrote:
>>
>>> Correction, that should be:
>>> template<typename T, typename U> auto bind_modifier(U functor) {
>>>    T modifier;
>>>    return std::bind(modifier(functor), modifier(functor));
>>> }
>>>
>>> And the modifier would have to be aware of the extra first parameter.
>>>
>>>
>>> On Wednesday, 7 May 2014 00:47:01 UTC+1, Diggory Blake wrote:
>>>>
>>>> Interesting, I came up with this based on that idea:
>>>>
>>>> struct memoize {
>>>>    template<typename T> memoized<T> operator()(T functor) { /* return a
>>>> callable object which caches calls to the functor */ }
>>>> };
>>>>
>>>> template<typename T, typename U> auto bind_modifier(U functor) {
>>>>    T modifier;
>>>>    return std::bind(functor, modifier(functor));
>>>> }
>>>>
>>>> auto f = bind_modifier<memoize>([](auto& f, int a) {
>>>>    return a > 1 ? f(f, a-1) + f(f, a-2) : a;
>>>> });
>>>>
>>>> I really like the syntax here as it means you can change the modifiers
>>>> without altering the lambda code. The only bit I'm concerned about is
>>>> whether the compiler would be able to optimise away the extra parameter.
>>>>
>>>> On Tuesday, 6 May 2014 20:56:05 UTC+1, Alex B wrote:
>>>>>
>>>>> For the record, here is a small (not so elegant) workaround using
>>>>> generic lambdas:
>>>>>
>>>>> auto f = [](int a)
>>>>> {
>>>>>     auto f2 = [](int a, auto f2)
>>>>>     {
>>>>>         if (a == 0)
>>>>>             return 0;
>>>>>         else
>>>>>             return f2(a-1, f2);
>>>>>     };
>>>>>     f2(a, f2);
>>>>> };
>>>>>
>>>>>
>>>>> On Tuesday, May 6, 2014 2:08:12 PM UTC-4, Diggory Blake wrote:
>>>>>
>>>>>> Apologies if this has already been addressed somewhere:
>>>>>>
>>>>>> When declaring a lambda, the type of the lambda is not available
>>>>>> until after the body of the lambda has been compiled:
>>>>>>
>>>>>> auto f = [&](int a){
>>>>>>    if (a == 0)
>>>>>>       return 0;
>>>>>>    else
>>>>>>       return f(a-1)+1; // This will fail: the type of 'f' is not yet
>>>>>> known, so it cannot be bound to the lambda
>>>>>> };
>>>>>>
>>>>>> This is understandable, and in this case without a significantly
>>>>>> smarter compiler is impossible to avoid (AFAIK). To make a recursive
>>>>>> lambda, you therefore have to wrap it in a std::function:
>>>>>>
>>>>>> std::function<int(int)> f = [&](int a){
>>>>>>    if (a == 0)
>>>>>>       return 0;
>>>>>>    else
>>>>>>       return f(a-1)+1; // This will work: the type of 'f' is already
>>>>>> known, as it does not depend on the type of the lambda
>>>>>> };
>>>>>>
>>>>>> This obviously is much less efficient, and when tested, compilers
>>>>>> were unable to optimise away the indirect call.
>>>>>>
>>>>>> It seems like there should be a special case where the compiler can
>>>>>> determine the type of a lambda before compiling the lambda body:
>>>>>>
>>>>>> auto f = [&f](int a) -> int { // At the point of the capture list,
>>>>>> the type of 'f' is not fully defined, but is known to be a lambda
>>>>>> (analogous to declaration of struct without body) and can therefore be
>>>>>> bound by reference (but not value)
>>>>>>    if (a == 0)
>>>>>>       return 0;
>>>>>>    else
>>>>>>       return f(a-1)+1; // This should work: the type of the lambda
>>>>>> was fully determined by the capture list, parameters and return type
>>>>>> };
>>>>>>
>>>>>> When the capture list, parameters and return type are all explicitly
>>>>>> specified, then the type of the lambda should be known within the lambda
>>>>>> body.
>>>>>>
>>>>>> Thoughts?
>>>>>>
>>>>>  --
>>>
>>> ---
>>> You received this message because you are subscribed to the Google
>>> Groups "ISO C++ Standard - Future Proposals" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
>>> an email to std-proposal...@isocpp.org <javascript:>.
>>>
>>> To post to this group, send email to std-pr...@isocpp.org <javascript:>.
>>> Visit this group at
>>> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>>>
>>
>>  --
>>
>> ---
>> You received this message because you are subscribed to a topic in the
>> Google Groups "ISO C++ Standard - Future Proposals" group.
>> To unsubscribe from this topic, visit
>> https://groups.google.com/a/isocpp.org/d/topic/std-proposals/bcBoAn226v8/unsubscribe
>> .
>> To unsubscribe from this group and all its topics, send an email to
>> std-proposal...@isocpp.org <javascript:>.
>> To post to this group, send email to std-pr...@isocpp.org <javascript:>.
>> Visit this group at
>> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>>
>
>

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_22_4332753.1399505726795
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Took it a little further and got something that allows any=
 number of modifiers to be applied without changing the lambda:<br><br><div=
 class=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); borde=
r-color: rgb(187, 187, 187); border-style: solid; border-width: 1px; word-w=
rap: break-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"=
><span style=3D"color: #000;" class=3D"styled-by-prettify">&nbsp; &nbsp; </=
span><span style=3D"color: #008;" class=3D"styled-by-prettify">auto</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> f </span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> bind_modifiers</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">([](</span><span style=3D"c=
olor: #008;" class=3D"styled-by-prettify">auto</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">&amp;</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> f</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">int</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
i</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">-&gt;</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #0=
08;" class=3D"styled-by-prettify">int</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br>&nbsp; &nbsp; &nbsp; &nbsp; </span><span style=3D"color: #008;=
" class=3D"styled-by-prettify">return</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify">i </span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>&lt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #066;" class=3D"styled-by-prettify">2</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">?</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> i </span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">:</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> f</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">i</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">-</span><span sty=
le=3D"color: #066;" class=3D"styled-by-prettify">2</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">+</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> f</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">i<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">-</span><sp=
an style=3D"color: #066;" class=3D"styled-by-prettify">1</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">);</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp; </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">},</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> memoize</span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">());</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br></span></div></code></div><br>You can al=
so supply arguments to modifiers:<br><br><div class=3D"prettyprint" style=
=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187);=
 border-style: solid; border-width: 1px; word-wrap: break-word;"><code clas=
s=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #000;=
" class=3D"styled-by-prettify">&nbsp; &nbsp; </span><span style=3D"color: #=
008;" class=3D"styled-by-prettify">auto</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> f </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> bind_modifiers</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">([](</span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">auto</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">&amp;</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> f</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">int</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> i</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">-&gt;</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">int</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbs=
p; &nbsp; &nbsp; </span><span style=3D"color: #008;" class=3D"styled-by-pre=
ttify">return</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify">i </span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #066;" class=3D"styled-by-prettify">2</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">?</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> i </span><span style=3D"color: #660;" class=3D"styled-by-prettify">:</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> f</span><span=
 style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify">i</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">-</span><span style=3D"color: #066;" cla=
ss=3D"styled-by-prettify">2</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">)</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">+=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> f</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify">i</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">-</span><span style=3D"color: #066;"=
 class=3D"styled-by-prettify">1</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">);</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"><br>&nbsp; &nbsp; </span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">},</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> trace</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">(</span><span style=3D"color: #080;" class=3D"styled-by-prettify">=
"You just called 'f'"</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">),</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> memoize</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>());</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><=
/span></div></code></div><br>And zero modifiers will work too (ie. you won'=
t have to supply the special first argument).<br><br>On Wednesday, 7 May 20=
14 17:30:51 UTC+1, Alex B  wrote:<blockquote class=3D"gmail_quote" style=3D=
"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex=
;"><div dir=3D"ltr">Very interesting library solution...<div><br><br><div c=
lass=3D"gmail_quote">On Tue, May 6, 2014 at 8:25 PM, Richard Smith <span di=
r=3D"ltr">&lt;<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mail=
to=3D"E4nOmzpykqIJ" onmousedown=3D"this.href=3D'javascript:';return true;" =
onclick=3D"this.href=3D'javascript:';return true;">ric...@metafoo.co.uk</a>=
&gt;</span> wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><font face=3D"courier =
new, monospace">#include &lt;utility&gt;<br></font></div><div><font face=3D=
"courier new, monospace">template&lt;typename F&gt; struct fixed_point {</f=
ont></div>
<div><font face=3D"courier new, monospace">&nbsp; F f;</font></div>
<div><font face=3D"courier new, monospace">&nbsp; template&lt;typename ...P=
&gt; decltype(auto) operator()(P &amp;&amp;...p) {</font></div><div><font f=
ace=3D"courier new, monospace">&nbsp; &nbsp; return f(*this, std::forward&l=
t;P&gt;(p)...);</font></div>

<div><font face=3D"courier new, monospace">&nbsp; }</font></div><div><font =
face=3D"courier new, monospace">};</font></div><div><font face=3D"courier n=
ew, monospace">template&lt;typename F&gt; fixed_point&lt;F&gt; fix(F &amp;&=
amp;f) { return { f }; }</font></div>

<div><font face=3D"courier new, monospace"><br></font></div><div><font face=
=3D"courier new, monospace">auto fib =3D fix([](auto &amp;fib, int n) -&gt;=
 int { return n &gt; 2 ? fib(n-1) + fib(n-2) : n; });</font></div><div><fon=
t face=3D"courier new, monospace">int main() { return fib(5); }</font></div=
>

<div><br><div class=3D"gmail_quote"><div><div>On Tue, May 6, 2014 at 4:50 P=
M, Diggory Blake <span dir=3D"ltr">&lt;<a href=3D"javascript:" target=3D"_b=
lank" gdf-obfuscated-mailto=3D"E4nOmzpykqIJ" onmousedown=3D"this.href=3D'ja=
vascript:';return true;" onclick=3D"this.href=3D'javascript:';return true;"=
>dig...@googlemail.com</a>&gt;</span> wrote:<br>

</div></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bo=
rder-left:1px #ccc solid;padding-left:1ex"><div><div><div dir=3D"ltr">Corre=
ction, that should be:<br><span style=3D"font-family:courier new,monospace"=
><div>
template&lt;typename T, typename U&gt; auto bind_modifier(U functor) {<br>
&nbsp;&nbsp; T modifier;<br></div>&nbsp;&nbsp; return std::bind(modifier(fu=
nctor), modifier(functor));<br>}</span><br><br>And the modifier would have =
to be aware of the extra first parameter.<div><div><br><br>On Wednesday, 7 =
May 2014 00:47:01 UTC+1, Diggory Blake  wrote:<blockquote class=3D"gmail_qu=
ote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding=
-left:1ex">

<div dir=3D"ltr">Interesting, I came up with this based on that idea:<br><b=
r><span style=3D"font-family:courier new,monospace">struct memoize {<br>&nb=
sp;&nbsp; template&lt;typename=20
T&gt; memoized&lt;T&gt; operator()(T functor) { /* return a callable object
 which caches calls to the functor */ }<br>};<br><br>template&lt;typename T=
, typename U&gt; auto bind_modifier(U functor) {<br>&nbsp;&nbsp; T modifier=
;<br>&nbsp;&nbsp; return std::bind(functor, modifier(functor));<br>}<br><br=
>auto f =3D bind_modifier&lt;memoize&gt;([](<u></u>auto<wbr>&amp; f, int a)=
 {<br>

&nbsp;&nbsp; return a &gt; 1 ? f(f, a-1) + f(f, a-2) : a;<br>});</span><br>=
<br>I really like the syntax here as it means you can change the modifiers =
without altering the lambda code. The only bit I'm concerned about is wheth=
er the compiler would be able to optimise away the extra parameter.<br>

<br>On Tuesday, 6 May 2014 20:56:05 UTC+1, Alex B  wrote:<blockquote class=
=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr"><div>For the record, here is a smal=
l (not so elegant) workaround using generic lambdas:</div>

<div>&nbsp;</div><div><div style=3D"border:1px solid rgb(187,187,187);word-=
wrap:break-word;background-color:rgb(250,250,250)"><code><div><span style=
=3D"color:rgb(0,0,136)">auto</span><span style=3D"color:rgb(0,0,0)"> f </sp=
an><span style=3D"color:rgb(102,102,0)">=3D</span><span style=3D"color:rgb(=
0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">[](</span><span style=
=3D"color:rgb(0,0,136)">int</span><span style=3D"color:rgb(0,0,0)"> a</span=
><span style=3D"color:rgb(102,102,0)">)</span><span style=3D"color:rgb(0,0,=
0)"><br>

</span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rg=
b(0,0,0)"><br>&nbsp; &nbsp; </span><span style=3D"color:rgb(0,0,136)">auto<=
/span><span style=3D"color:rgb(0,0,0)"> f2 </span><span style=3D"color:rgb(=
102,102,0)">=3D</span><span style=3D"color:rgb(0,0,0)"> </span><span style=
=3D"color:rgb(102,102,0)">[](</span><span style=3D"color:rgb(0,0,136)">int<=
/span><span style=3D"color:rgb(0,0,0)"> a</span><span style=3D"color:rgb(10=
2,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"c=
olor:rgb(0,0,136)">auto</span><span style=3D"color:rgb(0,0,0)"> f2</span><s=
pan style=3D"color:rgb(102,102,0)">)</span><span style=3D"color:rgb(0,0,0)"=
><br>

&nbsp; &nbsp; </span><span style=3D"color:rgb(102,102,0)">{</span><span sty=
le=3D"color:rgb(0,0,0)"><br>&nbsp; &nbsp; &nbsp; &nbsp; </span><span style=
=3D"color:rgb(0,0,136)">if</span><span style=3D"color:rgb(0,0,0)"> </span><=
span style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)=
">a </span><span style=3D"color:rgb(102,102,0)">=3D=3D</span><span style=3D=
"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">0</span><sp=
an style=3D"color:rgb(102,102,0)">)</span><span style=3D"color:rgb(0,0,0)">=
<br>

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style=3D"color:rgb(0=
,0,136)">return</span><span style=3D"color:rgb(0,0,0)"> </span><span style=
=3D"color:rgb(0,102,102)">0</span><span style=3D"color:rgb(102,102,0)">;</s=
pan><span style=3D"color:rgb(0,0,0)"><br>

&nbsp; &nbsp; &nbsp; &nbsp; </span><span style=3D"color:rgb(0,0,136)">else<=
/span><span style=3D"color:rgb(0,0,0)"><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbs=
p; &nbsp; </span><span style=3D"color:rgb(0,0,136)">return</span><span styl=
e=3D"color:rgb(0,0,0)"> f2</span><span style=3D"color:rgb(102,102,0)">(</sp=
an><span style=3D"color:rgb(0,0,0)">a</span><span style=3D"color:rgb(102,10=
2,0)">-</span><span style=3D"color:rgb(0,102,102)">1</span><span style=3D"c=
olor:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> f2</span><sp=
an style=3D"color:rgb(102,102,0)">);</span><span style=3D"color:rgb(0,0,0)"=
><br>

&nbsp; &nbsp; </span><span style=3D"color:rgb(102,102,0)">};</span><span st=
yle=3D"color:rgb(0,0,0)"><br>&nbsp; &nbsp; f2</span><span style=3D"color:rg=
b(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">a</span><span style=
=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> f2</spa=
n><span style=3D"color:rgb(102,102,0)">);</span><span style=3D"color:rgb(0,=
0,0)"><br>

</span><span style=3D"color:rgb(102,102,0)">};</span></div></code></div><br=
></div><div><br>On Tuesday, May 6, 2014 2:08:12 PM UTC-4, Diggory Blake wro=
te:</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8e=
x;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px=
;border-left-style:solid">

<div dir=3D"ltr">Apologies if this has already been addressed somewhere:<br=
><br>When declaring a lambda, the type of the lambda is not available until=
 after the body of the lambda has been compiled:<br><br><span style=3D"font=
-family:courier new,monospace">auto f =3D [&amp;](int a){<br>

&nbsp;&nbsp; if (a =3D=3D 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br=
>&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return f(a-1)+1; // Th=
is will fail: the type of 'f' is not yet known, so it cannot be bound to th=
e lambda<br>};</span><br><br>This is understandable, and in this case witho=
ut a significantly smarter compiler is impossible to avoid (AFAIK). To make=
 a recursive lambda, you therefore have to wrap it in a std::function:<br>

<br><span style=3D"font-family:courier new,monospace">std::function&lt;int(=
int)&gt; f =3D  [&amp;](int a){<br>&nbsp;&nbsp; if (a =3D=3D 0)<br>&nbsp;&n=
bsp;&nbsp;&nbsp;&nbsp; return 0;<br>&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;=
&nbsp;&nbsp; return f(a-1)+1; // This will work: the type of 'f' is already=
 known, as it does not depend on the type of the lambda<br>

};</span><br><br>This obviously is much less efficient, and when tested, co=
mpilers were unable to optimise away the indirect call.<br><br>It seems lik=
e there should be a special case where the compiler can determine the type =
of a lambda before compiling the lambda body:<br>

<br><span style=3D"font-family:courier new,monospace">auto f =3D [&amp;f](i=
nt a) -&gt; int { // At the point of the capture list, the type of 'f' is n=
ot fully defined, but is known to be a lambda (analogous to declaration of =
struct without body) and can therefore be bound by reference (but not value=
)<br>

&nbsp;&nbsp; if (a =3D=3D 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br=
>&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return f(a-1)+1; // Th=
is should work: the type of the lambda was fully determined by the capture =
list, parameters and return type<br>};</span><br><br>When the capture list,=
 parameters and return type are all explicitly specified, then the type of =
the lambda should be known within the lambda body.<br>

<br>Thoughts?<br></div></blockquote></div></blockquote></div></blockquote><=
/div></div></div></div></div><div><div><span><font color=3D"#888888">

<p></p>

-- <br>
<br>
--- <br>
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"=
E4nOmzpykqIJ" onmousedown=3D"this.href=3D'javascript:';return true;" onclic=
k=3D"this.href=3D'javascript:';return true;">std-proposal...@<wbr>isocpp.or=
g</a>.</font></span><div>
<br>
To post to this group, send email to <a href=3D"javascript:" target=3D"_bla=
nk" gdf-obfuscated-mailto=3D"E4nOmzpykqIJ" onmousedown=3D"this.href=3D'java=
script:';return true;" onclick=3D"this.href=3D'javascript:';return true;">s=
td-pr...@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank" onmousedown=3D"this.href=3D'http://groups=
..google.com/a/isocpp.org/group/std-proposals/';return true;" onclick=3D"thi=
s.href=3D'http://groups.google.com/a/isocpp.org/group/std-proposals/';retur=
n true;">http://groups.google.com/a/<wbr>isocpp.org/group/std-<wbr>proposal=
s/</a>.<br>
</div></div></div></blockquote></div><br></div></div><div><div>

<p></p>

-- <br>
<br>
--- <br>
You received this message because you are subscribed to a topic in the Goog=
le Groups "ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/=
a/isocpp.org/d/topic/std-proposals/bcBoAn226v8/unsubscribe" target=3D"_blan=
k" onmousedown=3D"this.href=3D'https://groups.google.com/a/isocpp.org/d/top=
ic/std-proposals/bcBoAn226v8/unsubscribe';return true;" onclick=3D"this.hre=
f=3D'https://groups.google.com/a/isocpp.org/d/topic/std-proposals/bcBoAn226=
v8/unsubscribe';return true;">https://groups.google.com/a/<wbr>isocpp.org/d=
/topic/std-<wbr>proposals/bcBoAn226v8/<wbr>unsubscribe</a>.<br>

To unsubscribe from this group and all its topics, send an email to <a href=
=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"E4nOmzpykqIJ" o=
nmousedown=3D"this.href=3D'javascript:';return true;" onclick=3D"this.href=
=3D'javascript:';return true;">std-proposal...@<wbr>isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"javascript:" target=3D"_bla=
nk" gdf-obfuscated-mailto=3D"E4nOmzpykqIJ" onmousedown=3D"this.href=3D'java=
script:';return true;" onclick=3D"this.href=3D'javascript:';return true;">s=
td-pr...@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank" onmousedown=3D"this.href=3D'http://groups=
..google.com/a/isocpp.org/group/std-proposals/';return true;" onclick=3D"thi=
s.href=3D'http://groups.google.com/a/isocpp.org/group/std-proposals/';retur=
n true;">http://groups.google.com/a/<wbr>isocpp.org/group/std-<wbr>proposal=
s/</a>.<br>
</div></div></blockquote></div><br></div></div>
</blockquote></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_22_4332753.1399505726795--

.


Author: Jim Porter <jvp4846@g.rit.edu>
Date: Wed, 7 May 2014 16:52:03 -0700 (PDT)
Raw View
------=_Part_112_3364329.1399506723932
Content-Type: text/plain; charset=UTF-8

On Tuesday, May 6, 2014 6:47:01 PM UTC-5, Diggory Blake wrote:
>
> Interesting, I came up with this based on that idea:
>
> struct memoize {
>    template<typename T> memoized<T> operator()(T functor) { /* return a
> callable object which caches calls to the functor */ }
> };
>
> template<typename T, typename U> auto bind_modifier(U functor) {
>    T modifier;
>    return std::bind(functor, modifier(functor));
> }
>
> auto f = bind_modifier<memoize>([](auto& f, int a) {
>    return a > 1 ? f(f, a-1) + f(f, a-2) : a;
> });
>
> I really like the syntax here as it means you can change the modifiers
> without altering the lambda code. The only bit I'm concerned about is
> whether the compiler would be able to optimise away the extra parameter.
>

(Not?) coincidentally, this is exactly what I did for a memoization library
I was tinkering with: <https://github.com/jimporter/memo>.

- Jim

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_112_3364329.1399506723932
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Tuesday, May 6, 2014 6:47:01 PM UTC-5, Diggory Blake wr=
ote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex=
;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">Interesti=
ng, I came up with this based on that idea:<br><br><span style=3D"font-fami=
ly:courier new,monospace">struct memoize {<br>&nbsp;&nbsp; template&lt;type=
name=20
T&gt; memoized&lt;T&gt; operator()(T functor) { /* return a callable object
 which caches calls to the functor */ }<br>};<br><br>template&lt;typename T=
, typename U&gt; auto bind_modifier(U functor) {<br>&nbsp;&nbsp; T modifier=
;<br>&nbsp;&nbsp; return std::bind(functor, modifier(functor));<br>}<br><br=
>auto f =3D bind_modifier&lt;memoize&gt;([](<wbr>auto&amp; f, int a) {<br>&=
nbsp;&nbsp; return a &gt; 1 ? f(f, a-1) + f(f, a-2) : a;<br>});</span><br><=
br>I really like the syntax here as it means you can change the modifiers w=
ithout altering the lambda code. The only bit I'm concerned about is whethe=
r the compiler would be able to optimise away the extra parameter.<br></div=
></blockquote><div><br>(Not?) coincidentally, this is exactly what I did fo=
r a memoization library I was tinkering with: &lt;https://github.com/jimpor=
ter/memo&gt;.<br><br>- Jim<br></div></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_112_3364329.1399506723932--

.