Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Why not add a feature to let lambda reference itself?

283 views
Skip to first unread message

rockeet

unread,
Mar 5, 2012, 2:35:57 PM3/5/12
to
Why C++ committee is so rigidity? They define lambda as exactly the
academism, and intentional didn't add a lambda self reference.
The best solution I have found is to bind the lambda to a
std::function<...> object.

The code snippet which need recursive lambda:
class Automata {
// more....
void print_output() const { // use recursive lambda
std::string str;
std::function<void(state_id_t,state_id_t,char_t)> lambda =
[&](state_id_t source,state_id_t target,char_t c) {
str.push_back(c);
if (is_term(target))
cout <<str << '\n';
for_each_move(target, lambda);
str.resize(str.size()-1); // pop_back
};
for_each_move(initial_state, lambda);
}
// more....
};

This code print a Tree Shape Automata by DFS order. The Automata is
careful designed for memory & speed, the function of for_each_move
complex but fast, so it is a template member function to iterate over
each direct target of specified state:

template<class OP> // use ctz (count trailing zero)
void for_each_move(state_id_t curr, OP op) const;

If there are some mechanism of lambda self refence, this code should
be more efficient and concise ( [[]] is the assumed lambda self
reference):

void print_output() const { // use recursive lambda
std::string str;
for_each_move(initial_state,
[&](state_id_t source,state_id_t target,char_t c) {
str.push_back(c);
if (is_term(target))
cout <<str << '\n';
for_each_move(target, [[]]);
str.resize(str.size()-1); // pop_back
});
}


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Krzysztof Żelechowski

unread,
Mar 5, 2012, 6:21:22 PM3/5/12
to
rockeet wrote:

> Why C++ committee is so rigidity? They define lambda as exactly the
> academism, and intentional didn't add a lambda self reference.
> The best solution I have found is to bind the lambda to a
> std::function<...> object.
>

Can you write an ordinary function that can take itself as an argument?

Hint: you cannot, unless you erase its type.

To answer your question: because C++ has strong types.

HTH,
Chris

Zeljko Vrba

unread,
Mar 5, 2012, 6:21:50 PM3/5/12
to
On 2012-03-05, rockeet <roc...@gmail.com> wrote:
>
> Why C++ committee is so rigidity? They define lambda as exactly the
> academism, and intentional didn't add a lambda self reference.
> The best solution I have found is to bind the lambda to a
> std::function<...> object.
>
I guess that the need is too rare and the workaround too simple to
warrant even more complicated grammar that doesn't bring any new
semantics.

>
> If there are some mechanism of lambda self refence, this code should
> be more efficient and concise
>
Why do you think it would be more efficient? Even if the language
supported lambda self-reference, it would probably be compiled to
the same thing as you hand-coded it: otherwise, how could you support
infinite looping?

In particular, why do you think that the compiler couldn't match the
identifier within the lambda body with the name lambda is bound to and
use that for optimization?

I don't have a rigorous proof, but my hunch tells me that the compiler
would have to be able to solve the halting problem to generate "more
efficient" code.

Daniel Krügler

unread,
Mar 6, 2012, 1:10:30 AM3/6/12
to
Am 05.03.2012 20:35, schrieb rockeet:
> Why C++ committee is so rigidity? They define lambda as exactly the
> academism, and intentional didn't add a lambda self reference.
> The best solution I have found is to bind the lambda to a
> std::function<...> object.
>
> The code snippet which need recursive lambda:
> class Automata {
> // more....
> void print_output() const { // use recursive lambda
> std::string str;
> std::function<void(state_id_t,state_id_t,char_t)> lambda =
> [&](state_id_t source,state_id_t target,char_t c) {
> str.push_back(c);
> if (is_term(target))
> cout<<str<< '\n';
> for_each_move(target, lambda);
> str.resize(str.size()-1); // pop_back
> };
> for_each_move(initial_state, lambda);
> }
> // more....
> };
>
> This code print a Tree Shape Automata by DFS order. The Automata is
> careful designed for memory& speed, the function of for_each_move
> complex but fast, so it is a template member function to iterate over
> each direct target of specified state:
>
> template<class OP> // use ctz (count trailing zero)
> void for_each_move(state_id_t curr, OP op) const;
>
> If there are some mechanism of lambda self refence, this code should
> be more efficient and concise ( [[]] is the assumed lambda self
> reference):
>
> void print_output() const { // use recursive lambda
> std::string str;
> for_each_move(initial_state,
> [&](state_id_t source,state_id_t target,char_t c) {
> str.push_back(c);
> if (is_term(target))
> cout<<str<< '\n';
> for_each_move(target, [[]]);
> str.resize(str.size()-1); // pop_back
> });
> }

Arguably this would be implementable, but it nonetheless looks like a
corner-case to me and questionable whether the effort is worth it. Why
not using a user-defined function object, if this use-case is so
important for you? Lambda-closures were invented to simplify the typical
examples, they have clear limitations and at some point a user-defined
functor is the right way to go.(*)

Greetings from Bremen,

Daniel Krügler

(*) This is not supposed to mean that they should not be improved, but I
find several other constraints much more limiting, e.g. the current
constraints on the captures (not being allowed to capture non-local
entities), or the lack of support for capturing move-only types by value.

rockeet

unread,
Mar 6, 2012, 1:12:10 AM3/6/12
to
On Mar 6, 7:21 am, Zeljko Vrba <mordor.nos...@fly.srk.fer.hr> wrote:
> On 2012-03-05, rockeet <rock...@gmail.com> wrote:
>
> > Why C++ committee is so rigidity? They define lambda as exactly the
> > academism, and intentional didn't add a lambda self reference.
> > The best solution I have found is to bind the lambda to a
> > std::function<...> object.
>
> I guess that the need is too rare and the workaround too simple to
> warrant even more complicated grammar that doesn't bring any new
> semantics.
>
>
>
> > If there are some mechanism of lambda self refence, this code should
> > be more efficient and concise
>
> Why do you think it would be more efficient? Even if the language
> supported lambda self-reference, it would probably be compiled to
> the same thing as you hand-coded it: otherwise, how could you support
> infinite looping?
>
> In particular, why do you think that the compiler couldn't match the
> identifier within the lambda body with the name lambda is bound to and
> use that for optimization?
>
> I don't have a rigorous proof, but my hunch tells me that the compiler
> would have to be able to solve the halting problem to generate "more
> efficient" code.

{ quoted clc++m banner removed -mod }

std::function<...> incurred many unnecessary forward function call,
for efficiency, the code in production was written as:

struct DFS_Outputer {
const Automata* aut;
std::string* str;
DFS_Outputer(const Automata* aut, std::string* str)
: aut(aut), str(str) {}
void operator()(state_id_t, state_id_t target, char_t c) const
{
str->push_back(c);
if (aut->is_term(target))
cout << *str << '\n';
aut->for_each_move(target, *this);
str->resize(str->size()-1); // pop_back
}
};
void Automata::print_output() const {
std::string str;
for_each_move(initial_state, DFS_Outputer(this, &str));
}
This is ugly and redundant, but this is the most efficient way. This
is my first use case of C++11 lambda, but it beat me in this way.

rockeet

unread,
Mar 6, 2012, 1:13:01 AM3/6/12
to
On Mar 6, 7:21 am, Krzysztof Żelechowski <giecr...@stegny.2a.pl>
wrote:
> rockeet wrote:
> > Why C++ committee is so rigidity? They define lambda as exactly the
> > academism, and intentional didn't add a lambda self reference.
> > The best solution I have found is to bind the lambda to a
> > std::function<...> object.
>
> Can you write an ordinary function that can take itself as an argument?
>
> Hint: you cannot, unless you erase its type.
>
> To answer your question: because C++ has strong types.

{ quoted signature and banner removed -mod }

This use case didn't take lambda itself as an argument, it just
recursive calling itself.

Zeljko Vrba

unread,
Mar 6, 2012, 4:10:09 PM3/6/12
to
On 2012-03-06, rockeet <roc...@gmail.com> wrote:
>
> std::function<...> incurred many unnecessary forward function call,
>
i believe you, but could you please explain in more detail what exactly
do you mean? what unneccessary calls were generated?

marcin...@gmail.com

unread,
Mar 6, 2012, 4:17:03 PM3/6/12
to
Wouldn't using 'auto' instead of 'std::function<...>' fix the problem?

Cheers,
Marcin

Daniel Krügler

unread,
Mar 6, 2012, 5:38:50 PM3/6/12
to
Am 06.03.2012 22:17, schrieb marcin...@gmail.com:
> Wouldn't using 'auto' instead of 'std::function<...>' fix the problem?

No, this won't work, see [dcl.spec.auto] p3:

"The name of the variable being declared shall not appear in the
initializer expression."

HTH & Greetings from Bremen,

Daniel Krügler

Gene Bushuyev

unread,
Mar 7, 2012, 3:55:37 AM3/7/12
to
On Mar 5, 11:35 am, rockeet <rock...@gmail.com> wrote:
> Why C++ committee is so rigidity? They define lambda as exactly the
> academism, and intentional didn't add a lambda self reference.
> The best solution I have found is to bind the lambda to a
> std::function<...> object.

This is one example of a general problem of standard not defining
syntax for recursive lambdas. I stumbled upon this problem when using
lambdas for defining parser generator rules (previous discussion
http://groups.google.com/group/comp.std.c++/browse_thread/thread/5b472069719d7c6a/51a56bac80ffc2d9
)

I see it as an omission in the standard, because there are no good
reasons disallowing it. Granted, it's not very often needed, but same
can be said about regular functions.

George Neuner

unread,
Mar 7, 2012, 7:47:42 PM3/7/12
to
On Mon, 5 Mar 2012 11:35:57 -0800 (PST), rockeet <roc...@gmail.com>
wrote:

>Why C++ committee is so rigidity? They define lambda as exactly the
>academism, and intentional didn't add a lambda self reference.
>The best solution I have found is to bind the lambda to a
>std::function<...> object.

There is nothing unusual about this. Although there may indeed exist
a language with self referencing closures, all the ones I know of that
support closure creation - Lisp, Scheme, ((O)?Ca)?ML, Haskell,
Smalltalk - create *anonymous* functions which must be bound to an
identifier for delayed invocation (such as in the case of recursion).

The major difference is that C++ has, IMO, a particularly ugly syntax
for lambda and for binding the resulting anonymous function to an
identifier. Given the existing type system I don't see how the syntax
could be improved significantly ... but that's a different discussion.

George

Roman W

unread,
Mar 8, 2012, 7:46:37 PM3/8/12
to
On Thursday, March 8, 2012 12:47:42 AM UTC, George Neuner wrote:
> On Mon, 5 Mar 2012 11:35:57 -0800 (PST), rockeet <roc...@gmail.com>
> wrote:
>
> >Why C++ committee is so rigidity? They define lambda as exactly the
> >academism, and intentional didn't add a lambda self reference.
> >The best solution I have found is to bind the lambda to a
> >std::function<...> object.
>
> There is nothing unusual about this. Although there may indeed exist
> a language with self referencing closures, all the ones I know of that
> support closure creation - Lisp, Scheme, ((O)?Ca)?ML, Haskell,
> Smalltalk - create *anonymous* functions which must be bound to an
> identifier for delayed invocation (such as in the case of recursion).
>
> The major difference is that C++ has, IMO, a particularly ugly syntax
> for lambda and for binding the resulting anonymous function to an
> identifier. Given the existing type system I don't see how the syntax
> could be improved significantly ... but that's a different discussion.

Since a lambda is always a function object, couldn't you call it as

(*this)(arg1, arg2, ...);

?

RW

Christopher Creutzig

unread,
Mar 10, 2012, 2:22:22 PM3/10/12
to
On 3/9/12 1:46 AM, Roman W wrote:

> Since a lambda is always a function object, couldn't you call it as
>
> (*this)(arg1, arg2, ...);

No, see §5.1.2.7:

| […] for purposes of […] determining the type and value of this
| (9.3.2) […], the compound-statement is considered in the context of
| the lambda-expression.


Christopher

George Neuner

unread,
Mar 10, 2012, 2:26:34 PM3/10/12
to
On Thu, 8 Mar 2012 16:46:37 -0800 (PST), Roman W
<bloody...@gazeta.pl> wrote:

>Since a lambda is always a function object, couldn't you call it as
>
>(*this)(arg1, arg2, ...);

AFAIK, there is no technical reason why that could not be done.

However, my understanding - which obviously may be wrong - is that
lambdas generally are implemented as an ad hoc class with a static
member function. No instance of any object is created and thus no
"this" pointer is available.

Maybe someone else knows for certain.
George

Daniel Krügler

unread,
Mar 11, 2012, 1:59:39 AM3/11/12
to
Am 10.03.2012 20:26, schrieb George Neuner:
> On Thu, 8 Mar 2012 16:46:37 -0800 (PST), Roman W
> <bloody...@gazeta.pl> wrote:
>
>> Since a lambda is always a function object, couldn't you call it as
>>
>> (*this)(arg1, arg2, ...);
>
> AFAIK, there is no technical reason why that could not be done.

Well, it would only be possible to change this for lambda-closures that
are not defined in class-scope, otherwise this would silently change the
semantics of existing lambda expressions. As Christopher pointed out,
the expression within the lambda-closure is considered in the context of
the lambda-expression, which means that 'this' always refers to an
"outer" this.

> However, my understanding - which obviously may be wrong - is that
> lambdas generally are implemented as an ad hoc class with a static
> member function. No instance of any object is created and thus no
> "this" pointer is available.

No, this model does not apply (modulo some special cases where the
difference wouldn't be observable). The function call expression of the
lambda closure is defined in terms of a non-static member function,
anything else would be hard to specify in the presence of a captures.
Which means that a lambda-expression behaves like a normal function
object types defined by a class type. Given C++11' compile-time
deduction capabilities, the difference would also be easily observable.

HTH & Greetings from Bremen,

Daniel Krügler


Miles Bader

unread,
Mar 11, 2012, 1:59:58 AM3/11/12
to
George Neuner <gneu...@comcast.net> writes:
>>Since a lambda is always a function object, couldn't you call it as
>>
>>(*this)(arg1, arg2, ...);
>
> AFAIK, there is no technical reason why that could not be done.
>
> However, my understanding - which obviously may be wrong - is that
> lambdas generally are implemented as an ad hoc class with a static
> member function. No instance of any object is created and thus no
> "this" pointer is available.

Er, not to mention that people very commonly want to capture a
surrounding "this" variable, so it wouldn't be good for lambdas to
define their own "this", at least by default.

-miles

--
((lambda (x) (list x x)) (lambda (x) (list x x)))

Roman W

unread,
Mar 11, 2012, 3:02:13 AM3/11/12
to
On Saturday, March 10, 2012 7:22:22 PM UTC, Christopher Creutzig wrote:
> On 3/9/12 1:46 AM, Roman W wrote:
>
> > Since a lambda is always a function object, couldn't you call it as
> >
> > (*this)(arg1, arg2, ...);
>
> No, see §5.1.2.7:
>
> | […] for purposes of […] determining the type and value of this
> | (9.3.2) […], the compound-statement is considered in the context of
> | the lambda-expression.

Do you mean that "this" would always refer to the (possible) object
creating the lambda function?

RW

Roman W

unread,
Mar 11, 2012, 3:02:31 AM3/11/12
to
On Saturday, March 10, 2012 7:26:34 PM UTC, George Neuner wrote:
> On Thu, 8 Mar 2012 16:46:37 -0800 (PST), Roman W
> <bloody...@gazeta.pl> wrote:
>
> >Since a lambda is always a function object, couldn't you call it as
> >
> >(*this)(arg1, arg2, ...);
>
> AFAIK, there is no technical reason why that could not be done.
>
> However, my understanding - which obviously may be wrong - is that
> lambdas generally are implemented as an ad hoc class with a static
> member function. No instance of any object is created and thus no
> "this" pointer is available.

If there is no object, then where do the references to the variables
captured by reference go? On the stack?

RW

rockeet

unread,
Mar 11, 2012, 3:03:29 AM3/11/12
to
On 3月11日, 上午3时26分, George Neuner <gneun...@comcast.net> wrote:
> On Thu, 8 Mar 2012 16:46:37 -0800 (PST), Roman W
>
> <bloody_rab...@gazeta.pl> wrote:
> >Since a lambda is always a function object, couldn't you call it as
>
> >(*this)(arg1, arg2, ...);
>
> AFAIK, there is no technical reason why that could not be done.
>
> However, my understanding - which obviously may be wrong - is that
> lambdas generally are implemented as an ad hoc class with a static
> member function. No instance of any object is created and thus no
> "this" pointer is available.
>
> Maybe someone else knows for certain.

{ quoted clc++m banner removed -mod }

No, It's not a static member function, it's a non-static member
function, otherwise variables in the context can't be captured without
incurring global objects.

Roman W

unread,
Mar 11, 2012, 9:48:41 PM3/11/12
to
On Sunday, March 11, 2012 6:59:39 AM UTC, Daniel Krügler wrote:
> Am 10.03.2012 20:26, schrieb George Neuner:
> > On Thu, 8 Mar 2012 16:46:37 -0800 (PST), Roman W
> > <bloody...@gazeta.pl> wrote:
> >
> >> Since a lambda is always a function object, couldn't you call it as
> >>
> >> (*this)(arg1, arg2, ...);
> >
> > AFAIK, there is no technical reason why that could not be done.
>
> Well, it would only be possible to change this for lambda-closures that
> are not defined in class-scope, otherwise this would silently change the
> semantics of existing lambda expressions. As Christopher pointed out,
> the expression within the lambda-closure is considered in the context of
> the lambda-expression, which means that 'this' always refers to an
> "outer" this.

Thanks. But it is possible to define a new keyword for this purpose, for
example "self". If this was done when introducing the lambda functions
in C++, there would be no backward compatibility problem. If we wait,
there will be the question of existing correct code being broken by the
introduction of new keyword inside lambda functions.

RW

Christopher Creutzig

unread,
Mar 11, 2012, 9:55:04 PM3/11/12
to
On 3/11/12 8:02 AM, Roman W wrote:
> On Saturday, March 10, 2012 7:22:22 PM UTC, Christopher Creutzig wrote:

>> No, see §5.1.2.7:
>>
>> | […] for purposes of […] determining the type and value of this
>> | (9.3.2) […], the compound-statement is considered in the context of
>> | the lambda-expression.
>
> Do you mean that "this" would always refer to the (possible) object
> creating the lambda function?

Right. And, to be honest, I find that much more intuitive. It allows
writing something like this sketch:

class ButtonController {
// ...
public:
void attach(Button *b) {
// ...
b->setCallback([&b]() -> void { onClicked(b) });
}
protected:
virtual void onClicked(Button *b) = 0;
}


--
Der Erleuchtete rangiert in seiner von Selbstzweifeln freien
Erkenntnissicherheit nun einmal über dem banal nur logisch Denkenden.
(Klaus-R. Löffler)

Francis Glassborow

unread,
Mar 12, 2012, 8:38:25 PM3/12/12
to
On 12/03/2012 01:48, Roman W wrote:
> On Sunday, March 11, 2012 6:59:39 AM UTC, Daniel Krügler wrote:
>> Am 10.03.2012 20:26, schrieb George Neuner:
>>> On Thu, 8 Mar 2012 16:46:37 -0800 (PST), Roman W
>>> <bloody...@gazeta.pl> wrote:
>>>
>>>> Since a lambda is always a function object, couldn't you call it as
>>>>
>>>> (*this)(arg1, arg2, ...);
>>>
>>> AFAIK, there is no technical reason why that could not be done.
>>
>> Well, it would only be possible to change this for lambda-closures that
>> are not defined in class-scope, otherwise this would silently change the
>> semantics of existing lambda expressions. As Christopher pointed out,
>> the expression within the lambda-closure is considered in the context of
>> the lambda-expression, which means that 'this' always refers to an
>> "outer" this.
>
> Thanks. But it is possible to define a new keyword for this purpose, for
> example "self". If this was done when introducing the lambda functions
> in C++, there would be no backward compatibility problem. If we wait,
> there will be the question of existing correct code being broken by the
> introduction of new keyword inside lambda functions.

Then the horse has already left the stable. I also suspect that WG21 would have big problems with introducing such a keyword as it is likely to be in wide use in existing code for whatever the individual programmer has chosen to use it for.

Francis

Frank Birbacher

unread,
Mar 12, 2012, 8:47:13 PM3/12/12
to
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi!

Am 12.03.12 02:55, schrieb Christopher Creutzig:
> On 3/11/12 8:02 AM, Roman W wrote:
>> Do you mean that "this" would always refer to the (possible)
>> object creating the lambda function?
>
> Right. And, to be honest, I find that much more intuitive.

I agree here. The outer object and the lambda object compete for
"this." Refering to the outer comes in handy in so many applications.

> It allows writing something like this sketch:
>
> class ButtonController { // ... public: void attach(Button *b) { //
> ... b->setCallback([&b]() -> void { onClicked(b) });

Yeah :) and even this can be made shorter:
b->setCallback([=] { onClicked(b); });

Note that "b" is just a pointer. Capturing a pointer by reference is
both overkill and dangerous: the referred to pointer instance will be
gone after "attach" ends because its just a function parameter.
Additionally the "this" will not be captured at all when using
"[&b]". You need "[b,this]" or just "[=]".

Frank
-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.17 (Darwin)
Comment: GPGTools - http://gpgtools.org
Comment: keyserver x-hkp://pool.sks-keyservers.net

iEYEARECAAYFAk9eQUoACgkQhAOUmAZhnmpkdQCeIV6dJI4mYkrD3gfcnYliEyVS
gMUAoIs9hhLyVfC2DilNMkQFVlTjGQ/D
=AkQT
-----END PGP SIGNATURE-----


--

rockeet

unread,
Mar 13, 2012, 2:57:56 PM3/13/12
to
> Then the horse has already left the stable. I also suspect that WG21 would have big problems with introducing such a keyword as it is likely to be in wide use in existing code for whatever the individual programmer has chosen to use it for.
>
> Francis

sometimes a long ugly name may be useful, such as reinterpret_cast, in
this case the imaged keyword could be 'this_lambda' or 'lambda_self'
or 'lambda_recursively_call'

Dave Harris

unread,
Mar 14, 2012, 3:11:54 PM3/14/12
to
bloody...@gazeta.pl (Roman W) wrote (abridged):
> Thanks. But it is possible to define a new keyword for this
> purpose, for example "self". If this was done when introducing
> the lambda functions in C++, there would be no backward
> compatibility problem. If we wait, there will be the question of
> existing correct code being broken by the introduction of new
> keyword inside lambda functions.

It's already too late. But even if it wasn't, you seem to be saying that code like:

void demo() {
int self = 1; // OK?
auto lambda = [&] { ++self; }; // Proposed error?
}

should not compile. I don't agree. Variable names shouldn't turn into keywords just
because they are in a lambda expression.

-- Dave Harris, Nottingham, UK.

Gene Bushuyev

unread,
Mar 14, 2012, 3:14:33 PM3/14/12
to
On Mar 12, 5:38 pm, Francis Glassborow
It's too late for C++11, but it's too early to close this chapter.
After all, polymorphic lambdas are also waiting its hour, so I guess
this topic will inevitably be revisited. Why not to take care of
recursion as well.

Though "self" isn't a good candidate, the Standard could reuse "this"
keyword with a different syntax, for example "[this]" or "[]this"
could refer to the most enclosed closure, "[[this]]" or "[][]this" can
refer to second-level object, and so on. Another possibility is to use
empty square brackets for even more pithy syntax, i.e. [] - first
level closure object, [[]] or [][] - second-level, etc. Below are some
examples with this invented syntax:

auto fact = [](unsigned n)
{
// [] referring to current closure
return n ? n * [](n - 1) : 1;
};

auto fact1 = [](unsigned n)
{
// [[]] referring to the second level "this"
// compilation error if not used in a proper context
return n ? n * [[]](n - 1) : 1;
};

auto fact2 = [](unsigned n)
{
return fact1(n); // ok, [[]] refers to this closure
};

auto fact3 = [](unsigned n)
{
// same
return [=]{ return n ? n * [[]](n - 1) : 1; }();
};

struct A {

// now let's make another step
// and allow in-class lambda initialization

auto fact { [](unsigned n) { return n ? n * [](n - 1) : 1; }};
};

Roman W

unread,
Mar 14, 2012, 6:18:48 PM3/14/12
to
On Tuesday, March 13, 2012 6:57:56 PM UTC, rockeet wrote:
> sometimes a long ugly name may be useful, such as reinterpret_cast, in
> this case the imaged keyword could be 'this_lambda' or 'lambda_self'
> or 'lambda_recursively_call'

I tried doing something like that:

int main(void)
{
auto recursive_lambda = [](unsigned int n){ return n; };
recursive_lambda = [&recursive_lambda](unsigned int n) { if (n <= 1) return static_cast<unsigned int>(1); else return n*recursive_lambda(n - 1); };
}


but apparently C++ lambdas have no = operator.

RW

Daniel Krügler

unread,
Mar 14, 2012, 8:12:51 PM3/14/12
to
Am 14.03.2012 23:18, schrieb Roman W:
> On Tuesday, March 13, 2012 6:57:56 PM UTC, rockeet wrote:
>> sometimes a long ugly name may be useful, such as reinterpret_cast, in
>> this case the imaged keyword could be 'this_lambda' or 'lambda_self'
>> or 'lambda_recursively_call'
>
> I tried doing something like that:
>
> int main(void)
> {
> auto recursive_lambda = [](unsigned int n){ return n; };
> recursive_lambda = [&recursive_lambda](unsigned int n) { if (n<= 1) return static_cast<unsigned int>(1); else return n*recursive_lambda(n - 1); };
> }
>
>
> but apparently C++ lambdas have no = operator.

They have a deleted copy-assignment operator, yes. But even if the
copy-assignment operator would *not* be deleted, above code wouldn't
work, because the second lambda-expression has a different type. In
fact, both could *not* be equal, because the second one has another data
member that corresponds to the reference-capture "recursive_lambda".

HTH & Greetings from Bremen,

Daniel Krügler


Daniel Krügler

unread,
Mar 15, 2012, 3:08:43 AM3/15/12
to
Am 15.03.2012 01:12, schrieb Daniel Krügler:
> Am 14.03.2012 23:18, schrieb Roman W:
>> On Tuesday, March 13, 2012 6:57:56 PM UTC, rockeet wrote:
>>> sometimes a long ugly name may be useful, such as reinterpret_cast, in
>>> this case the imaged keyword could be 'this_lambda' or 'lambda_self'
>>> or 'lambda_recursively_call'
>>
>> I tried doing something like that:
>>
>> int main(void)
>> {
>> auto recursive_lambda = [](unsigned int n){ return n; };
>> recursive_lambda = [&recursive_lambda](unsigned int n) { if (n<= 1)
>> return static_cast<unsigned int>(1); else return n*recursive_lambda(n
>> - 1); };
>> }
>>
>>
>> but apparently C++ lambdas have no = operator.
>
> They have a deleted copy-assignment operator, yes. But even if the
> copy-assignment operator would *not* be deleted, above code wouldn't
> work, because the second lambda-expression has a different type. In
> fact, both could *not* be equal, because the second one has another data
> member that corresponds to the reference-capture "recursive_lambda".

Returning to you experiment: If you are already willing to perform a
two-step process, there is no reason, why the following should not work:

#include <iostream>

int main()
{
auto lambda = [](unsigned int n){ return n; };
auto recursive_lambda = [&lambda](unsigned int n) { if (n <= 1)
return static_cast<unsigned int>(1); else return n*lambda(n - 1); };
std::cout << recursive_lambda(3) << std::endl;
}

recursive_lambda is not recursive in the strict sense, but it has the
same effect, because it invokes lambda recursively.

rockeet

unread,
Mar 18, 2012, 4:13:20 PM3/18/12
to
On 3月15日, 上午6时18分, Roman W <bloody_rab...@gazeta.pl> wrote:
> On Tuesday, March 13, 2012 6:57:56 PM UTC, rockeet wrote:
> > sometimes a long ugly name may be useful, such as reinterpret_cast, in
> > this case the imaged keyword could be 'this_lambda' or 'lambda_self'
> > or 'lambda_recursively_call'
>
> I tried doing something like that:
>
> int main(void)
> {
> auto recursive_lambda = [](unsigned int n){ return n; };
> recursive_lambda = [&recursive_lambda](unsigned int n) { if
(n <= 1) return static_cast<unsigned int>(1); else return
n*recursive_lambda(n - 1); };
>
> }
>
> but apparently C++ lambdas have no = operator.
>
> RW
>
> --
> [ Seehttp://www.gotw.ca/resources/clcm.htmfor info about ]
> [ comp.lang.c++.moderated. First time posters: Do this! ]

Why don't you name a variable 'reinterpret_cast'? just because they
are already a keyword?

terminator

unread,
Mar 28, 2012, 4:38:03 PM3/28/12
to
On Monday, March 12, 2012 5:18:41 AM UTC+3:30, Roman W wrote:
> On Sunday, March 11, 2012 6:59:39 AM UTC, Daniel Krügler wrote:
> > Am 10.03.2012 20:26, schrieb George Neuner:
> > > On Thu, 8 Mar 2012 16:46:37 -0800 (PST), Roman W
> > > <bloody...@gazeta.pl> wrote:
> > >
> > >> Since a lambda is always a function object, couldn't you call
> > >> it as
> > >> (*this)(arg1, arg2, ...);
> > >
> > > AFAIK, there is no technical reason why that could not be done.
> >
> > Well, it would only be possible to change this for lambda-closures
> > that are not defined in class-scope, otherwise this would silently
> > change the semantics of existing lambda expressions. As
> > Christopher pointed out, the expression within the lambda-closure
> > is considered in the context of the lambda-expression, which means
> > that 'this' always refers to an "outer" this.
>
> Thanks. But it is possible to define a new keyword for this purpose,
> for example "self". If this was done when introducing the lambda
> functions in C++, there would be no backward compatibility
> problem. If we wait, there will be the question of existing correct
> code being broken by the introduction of new keyword inside lambda
> functions.

why should lambdas be so Odd?
I understand that since every lambda is a singleton ,no general type
string is provided for them, **but** why should it be anonymous?

pascal has provided named function-local functions long ago, and since
they **have** names you can use them multiple times in different parts
of functions belonging to the same lexical hierarchy.

why are we banned to write sth like this:

[CONTEXT_ACCESS]myLambda(ARGS)->returnType
{
if (FINE)
return RESULT;
myLambda(PARAMS);
}

regards,
FM.

James K. Lowden

unread,
Mar 29, 2012, 12:53:33 AM3/29/12
to
On Wed, 28 Mar 2012 13:38:03 -0700 (PDT)
terminator <farid....@gmail.com> wrote:

> I understand that since every lambda is a singleton ,no general type
> string is provided for them, **but** why should it be anonymous?

Wouldn't a lambda with a name be something we've had from the
beginning, namely a functor?

--jkl

Roman W

unread,
Mar 29, 2012, 1:10:41 PM3/29/12
to
On Thursday, March 29, 2012 5:53:33 AM UTC+1, James K. Lowden wrote:
> On Wed, 28 Mar 2012 13:38:03 -0700 (PDT)
> terminator <farid....@gmail.com> wrote:
>
> > I understand that since every lambda is a singleton ,no general type
> > string is provided for them, **but** why should it be anonymous?
>
> Wouldn't a lambda with a name be something we've had from the
> beginning, namely a functor?

No, because the syntax to declare it would be lighter.

Haskell has something like that:

let factorial n = if n == 0 then 1 else n * (factorial (n - 1))

Simple & powerful.

RW

Seungbeom Kim

unread,
Mar 29, 2012, 11:46:02 PM3/29/12
to
On 2012-03-29 10:10, Roman W wrote:
> On Thursday, March 29, 2012 5:53:33 AM UTC+1, James K. Lowden wrote:
>> On Wed, 28 Mar 2012 13:38:03 -0700 (PDT)
>> terminator <farid....@gmail.com> wrote:
>>
>>> I understand that since every lambda is a singleton ,no general type
>>> string is provided for them, **but** why should it be anonymous?
>>
>> Wouldn't a lambda with a name be something we've had from the
>> beginning, namely a functor?
>
> No, because the syntax to declare it would be lighter.
>
> Haskell has something like that:
>
> let factorial n = if n == 0 then 1 else n * (factorial (n - 1))
>
> Simple & powerful.

long factorial(long n) { return (n == 0) ? 1 : (n * factorial(n - 1)); }

or

template <typename T>
T factorial(T n) { return (n == 0) ? 1 : (n * factorial(n - 1)); }

Isn't this simple and powerful enough?

--
Seungbeom Kim

Frank Birbacher

unread,
Mar 29, 2012, 11:53:52 PM3/29/12
to
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi!

Am 29.03.12 19:10, schrieb Roman W:
> Haskell has something like that:
>
> let factorial n = if n == 0 then 1 else n * (factorial (n - 1))

And in haskell there are also unnamed lambdas which cannot recursively
call themselves. The factorial above roughly translates to:

template<typename T>
T factorial(T const n) {
if(n == 0) return 1;
else return n * factorial<T>(n-1);
}

> Simple & powerful.

Just as with a regular function in C++.

BTW, typeerasure can do this:

#include <functional>

using namespace std;
typedef unsigned Number;

Number factorial(Number const outer_n)
{
typedef function<Number(Number)> Func;
Func rec;
rec = [&rec](Number const n) -> Number {
if(n == 0) return 1;
return n * rec(n-1);
};
return rec(outer_n);
}

#include <iostream>
#include <ostream>
int main()
{
for(Number i = 0; i < 10; ++i) {
std::cout << i << " -> " << factorial(i) << std::endl;
}
}

Frank
-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.17 (Darwin)
Comment: GPGTools - http://gpgtools.org
Comment: keyserver x-hkp://pool.sks-keyservers.net

iEYEARECAAYFAk902rcACgkQhAOUmAZhnmra3gCdEWDZskpB2tstfvTfxtK6dIO6
WyYAoIMmHXiRmlnMw48mhdc+nPJ5Zqfz
=I4pa
-----END PGP SIGNATURE-----

Roman W

unread,
Mar 30, 2012, 8:20:43 AM3/30/12
to
On Friday, March 30, 2012 4:53:52 AM UTC+1, Frank Birbacher wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Hi!
>
> Am 29.03.12 19:10, schrieb Roman W:
> > Haskell has something like that:
> >
> > let factorial n = if n == 0 then 1 else n * (factorial (n - 1))
>
> And in haskell there are also unnamed lambdas which cannot recursively
> call themselves. The factorial above roughly translates to:
>
> template<typename T>
> T factorial(T const n) {
> if(n == 0) return 1;
> else return n * factorial<T>(n-1);
> }
>
> > Simple & powerful.
>
> Just as with a regular function in C++.

No, because functions cannot be nested in C++.

>
> BTW, typeerasure can do this:
>
> #include <functional>
>
> using namespace std;
> typedef unsigned Number;
>
> Number factorial(Number const outer_n)
> {
> typedef function<Number(Number)> Func;
> Func rec;
> rec = [&rec](Number const n) -> Number {
> if(n == 0) return 1;
> return n * rec(n-1);
> };
> return rec(outer_n);
> }
>
> #include <iostream>
> #include <ostream>
> int main()
> {
> for(Number i = 0; i < 10; ++i) {
> std::cout << i << " -> " << factorial(i) << std::endl;
> }
> }

That's terribly long.

RW

Roman W

unread,
Mar 30, 2012, 8:21:13 AM3/30/12
to
On Friday, March 30, 2012 4:46:02 AM UTC+1, Seungbeom Kim wrote:
> On 2012-03-29 10:10, Roman W wrote:
> > On Thursday, March 29, 2012 5:53:33 AM UTC+1, James K. Lowden wrote:
> >> On Wed, 28 Mar 2012 13:38:03 -0700 (PDT)
> >> terminator <farid....@gmail.com> wrote:
> >>
> >>> I understand that since every lambda is a singleton ,no general type
> >>> string is provided for them, **but** why should it be anonymous?
> >>
> >> Wouldn't a lambda with a name be something we've had from the
> >> beginning, namely a functor?
> >
> > No, because the syntax to declare it would be lighter.
> >
> > Haskell has something like that:
> >
> > let factorial n = if n == 0 then 1 else n * (factorial (n - 1))
> >
> > Simple & powerful.
>
> long factorial(long n) { return (n == 0) ? 1 : (n * factorial(n - 1)); }
>
> or
>
> template <typename T>
> T factorial(T n) { return (n == 0) ? 1 : (n * factorial(n - 1)); }
>
> Isn't this simple and powerful enough?

You can't declare it within another function.

RW


--

terminator

unread,
Mar 31, 2012, 2:57:48 AM3/31/12
to
{ Please limit your text to fit within 80 columns, preferably around 70,
so that readers don't have to scroll horizontally to read each line.
This article has been reformatted manually by the moderator. -mod }

On Thursday, March 29, 2012 9:23:33 AM UTC+4:30, James K. Lowden wrote:
> On Wed, 28 Mar 2012 13:38:03 -0700 (PDT)
> terminator <farid....@gmail.com> wrote:
>
> > I understand that since every lambda is a singleton ,no general type
> > string is provided for them, **but** why should it be anonymous?
>
> Wouldn't a lambda with a name be something we've had from the
> beginning, namely a functor?
>
> --jkl
>

with no access to the caller`s context,you mean of course.

the anonymity of lambda was originally motivated to ease utilization
of <algorithm> members.
but more important than anonymity is the ability of lambda to use
automatic variables of its direct nest; this is what a function-local
function in pascal can do and I don`t remember I have ever seen a thing
in C/C++.


FM.

Gene Bushuyev

unread,
Mar 31, 2012, 2:59:04 AM3/31/12
to
On Mar 29, 8:46 pm, Seungbeom Kim <musip...@bawi.org> wrote:
> On 2012-03-29 10:10, Roman W wrote:
> > On Thursday, March 29, 2012 5:53:33 AM UTC+1, James K. Lowden wrote:
> >> On Wed, 28 Mar 2012 13:38:03 -0700 (PDT)
> >> terminator <farid.mehr...@gmail.com> wrote:
>
> >>> I understand that since every lambda is a singleton ,no general type
> >>> string is provided for them, **but** why should it be anonymous?
>
> >> Wouldn't a lambda with a name be something we've had from the
> >> beginning, namely a functor?
>
> > No, because the syntax to declare it would be lighter.
>
> > Haskell has something like that:
>
> > let factorial n = if n == 0 then 1 else n * (factorial (n - 1))
>
> > Simple & powerful.
>
> long factorial(long n) { return (n == 0) ? 1 : (n * factorial(n - 1)); }
>
> or
>
> template <typename T>
> T factorial(T n) { return (n == 0) ? 1 : (n * factorial(n - 1)); }
>
> Isn't this simple and powerful enough?

This misses the point. Factorial was only used as a simplest example
to demonstrate recursion. Your template function is not a lambda
function, it doesn't create closure capturing context. There is a need
for recursive lambda and the only way at present to achieve it in
general case is by using expensive virtual dispatch, e.g.

std::function<int (int)> factorial = [](int n) { return n ? n *
factorial(n-1) : 1; }


--

terminator

unread,
Apr 6, 2012, 4:13:30 PM4/6/12
to
since every lambda is a singleton the best way IMHO for compiler to
implement is to push a pointer to the stack frame of the caller and
call the lambda's "operator()".there is no need for a "this" pointer,
so basically it is similar to plain old functions with an implicit
pointer to the nesting context.The only thing currently missing is the
name that provides full support for what machine code already supports
via "enter/leave" pairs on x86 and "lnk/unlnk" on mc6000 as lexical
functions.

regards,
FM.

Dave Abrahams

unread,
Apr 6, 2012, 8:56:16 PM4/6/12
to
on Fri Apr 06 2012, terminator <farid.mehrabi-AT-gmail.com> wrote:

> since every lambda is a singleton...

It isn't:

template <class T>
int factorial(int x)
{
if (x == 0)
return 1;
auto mulx = [=](int y) { return x * y; }
return mulx(f(x-1));
}

HTH-ly y'rs,

--
Dave Abrahams
BoostPro Computing
http://www.boostpro.com
0 new messages