 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Edson Manoel Guest
|
Posted: Sat Jul 30, 2005 12:35 am Post subject: Lambda functions in C++0x? |
|
|
With all the discussion going on about STL algorithms vs. manual loops,
I think we should start to think if Lambda (or anonymous) functions can
still be a C++0x language feature, and how it's notation should be.
Sadly, lambda is not a proposal in BS evolution WG list
([url]http://www.research.att.com/~bs/evol-issues.html)[/url], it is only listed
as a "suggestion", and the only statement about it is:
| Quote: | ES017. Lambda.
???
|
The idea is that lambda (together with auto-types and language
concepts) would greatly improve code readability and allow a more
widespread usage of STL (and other generic) algorithms.
There is already some kind of support for lambda in some libraries like
Boost.Lambda, Boost.Spirit.Phoenix and FC++, but they are all imperfect
hacks... we still need to use binds and cannot do something as simple
as:
for_each(c.begin(), c.end(), _1->someMemberFunction(_1->someAttribute)
)
We cannot use 'for', 'if' and 'while' in the lambda, and those
libraries define hacks around this, like using if_, while_ and for_,
substituting { } for 'operator[]' and substituting the ';' terminator
for 'operator,' - for example (in Spirit):
for_each(c.begin(), c.end(),
if_(arg1 > 42)
[
cout << arg1 << " > 42n"
]
.else_
[
if_(arg1 == 42)
[
cout << arg1 << " == 42n"
]
.else_
[
cout << arg1 << " < 42n"
]
]
);
FC++ syntax is not too much different, and even has some strange
operators like %equal%, %multiplies% and %minus%. Also, I think that
the use of positional parameters in those libraries is ugly and very
low-level.
All of this starts to work against the programmer - instead of helping
him it difficults his life - readability and debugging capability are
almost completely thrown away - C++ starts to become some "freak"
language... if the intent of C++0x is to make C++ easier to learn, then
this is *not* the right direction.
Instead, lambda functions should be supported directly in the language,
without the need of those ugly hacks. Something as simple as this:
for_each(c.begin(), c.end(),
lambda(x){ x->someMemberFunction(x->someAttribute); } );
It simply defines an anonymous inlined function in that scope and pass
it as a functor (probably using the UnaryFunctor concept, if C++0x will
have concept support in the language). An example:
int threshold = 42;
for_each(c.begin, c.end(),
lambda(x){
if(x > threshold) {
cout << x << " > " << threshold << endl;
} else {
cout << x << " <= " << threshold << endl;
}
});
It could be "translated" by the compiler into something like
....
int threshold = 42;
template
if(x > threshold) {
cout << x << " > " << threshold << endl;
} else {
cout << x << " <= " << threshold << endl;
}
}
for_each(c.begin(), c.end(), anonymous_func
....
Well, it would need some kind of "function-inside-function" support (a
la gcc) to have access to the variables in the same scope (threshold in
this case). In this case, it would also need support to inlined
functors and to a "typeof" operator, but these are minor issues
(maybe).
Also the introduction of the 'lambda' keyword may be a problem... but
there is the possibility of using some already existing keyword, e.g:
for_each(c.begin(), c.end(), static(a){a += 1});
for_each(c.begin(), c.end(), inline(a){a += 1});
for_each(c.begin(), c.end(), auto(a){a += 1});
With "Container" concept support, it could become even better, e.g:
vector<int> c = {1, 2, 3, 4};
list<double> d = {1.5, 0.0, -2.0};
deque<float> r;
for_each(c, lambda(c_item){
for_each(d, lambda(d_item){
r.push_back(c_item * d_item); }); });
// r == {1.5, 0.0, -2.0, 3.0, 0.0, -4.0, 4.5, 0.0, -6.0, 6.0, 0.0,
-8.0};
I'm using the "for_each" example because it is very simple, but of
course lambda functions would bring benefits to the usage of other
algorithms like transform and accumulate.
So, what do you think about this syntax? I'm no compiler writer and I'm
not on a standards committee, but what do you think about the
feasibility of lambda functions being incorporated in C++0x, given the
benefits to the language they may bring??
Edson T. M. Manoel
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Zeljko Vrba Guest
|
Posted: Sat Jul 30, 2005 10:15 am Post subject: Fwd: Re: Lambda functions in C++0x? |
|
|
Sorry if this is duplicate, but my news provider doesn't know about
moderated groups.
From: Zeljko Vrba <first.last (AT) oss (DOT) unist.hr>
Newsgroups: comp.lang.c++.moderated
Subject: Re: Lambda functions in C++0x?
-----BEGIN PGP SIGNED MESSAGE-----
Hash: RIPEMD160
In article <1122667381.227705.195580 (AT) g43g2000cwa (DOT) googlegroups.com>, Edson Manoel wrote:
| Quote: |
Instead, lambda functions should be supported directly in the language,
without the need of those ugly hacks. Something as simple as this:
Uf.. you've given only simple examples of lambda. You didn't define |
*restrictions*. In true 'lambda-enabled' languages like Scheme and LISP,
the lambda has unlimited extent. Which brings us to the garbage collection
issue.
Are we allowed to return lambdas from functions? Store them in variables? What
if lambda references existing local variables? Take for example the
following simple code which is very natural in lisp:
template<typename RET>
RET make_lambda(int x)
{
int y = 2*x;
return lambda(z) { x + y; }
}
int main()
{
auto f = make_lambda(25);
cout << f(12) << endl;
return 0;
}
Now.. the lambda has to be allocated on the heap in order to have unlimited
extent (as it is called in lisp).. And in its 'closure' it has to store
copies both to x and y variables. Each time you call make_lambda you should
get a *new* lambda with its own copies of x,y variables. The closeure can be
deallocate only when there is no reference left to that lambda, for which you
need garbage collector. I doubt that compiler static analysis can deduce when
the lambda is safe to destroy.
For the same reason, anonymous classes in Java (poor lambda emulation, too)
can only reference 'final' stack variables.
Don't get me wrong: lambda and auto-types are two features that I really miss
in C++. I hope it won't remain only a dream :)
On the naming issue: I wouldn't call it lambda unless it is true lambda.
Better to (once again) overload the static keyword. inline makes even more
sense.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: For info see http://www.gnupg.org
iD8DBQFC6yY1FtofFpCIfhMRA9ykAKCFRQ0OgckUbuZDTJI5yZ8xJmY11gCfXGcy
tz/VXfV22MK0haQaIcoeHXU=
=aa/c
-----END PGP SIGNATURE-----
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Dave Harris Guest
|
Posted: Sun Jul 31, 2005 4:47 pm Post subject: Re: Lambda functions in C++0x? |
|
|
[email]e.tadeu (AT) gmail (DOT) com[/email] (Edson Manoel) wrote (abridged):
| Quote: | With all the discussion going on about STL algorithms vs. manual loops,
I think we should start to think if Lambda (or anonymous) functions can
still be a C++0x language feature, and how it's notation should be.
|
This has been discussed in the past. Searching google for "lambda" in
comp.lang.c++.moderated will turn up some long threads. A fairly recent
one is entitled "Lambda - let's write it down" and is well worth reading.
Key questions include whether lambdas should be compatible with plain C
function pointers, or whether they should be full objects. If full
objects, can they use inheritance, virtual functions, be allocated from
the heap etc? Can they access variables from the enclosing scope, and if
so, do they get a reference or a copy?
I suggest we support both function lambdas and object lambdas, and only
allow object lambdas to use variables from their enclosing scope. For
example, this:
void print_cout( int *first, int *last ) {
for_each( first, last, void inline( int x ) {
cout << x; // cout is a global.
} );
}
would produce an unnamed function; the argument to for_each is a
pointer-to-function with all that implies. It cannot use
local variables.
Changing the "inline" keyword to "struct" makes an object:
void print_stream( int *first, int *last, ostream &os ) {
for_each( first, last, void struct( int x ) {
os << x; // os is a local variable.
} );
}
The argument to for_each is an instance of an anonymous struct. The struct
would have a reference to the stream, a constructor which initialised it,
and an operator().
Some people felt that the above syntax was too verbose, especially
compared to current solutions using libraries and "_1".
The most controversial area is "upward lambdas", that is, returning object
lambdas from functions. I argued we should use operator new() and
inheritance, and return a pointer to the object, and bind variable from
the enclosed scope by reference but possibly extend their lifetime
automatically.
Raoul Gough argued that variables should be bound by value, and lambdas
returned by value, which reduced the amount of indirection. It led to the
issue of naming the type of the lambda, and also needed some way to get
reference semantics when that was desired.
I could see the merits in his position. I don't think we're ready to make
a final decision on upward lambdas. More discussion and experimentation is
needed. Probably we should not let this controversy get in the way of
adding downward lambdas, which are much simpler.
-- Dave Harris, Nottingham, UK.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Hyman Rosen Guest
|
Posted: Mon Aug 01, 2005 8:03 am Post subject: Re: Fwd: Re: Lambda functions in C++0x? |
|
|
Zeljko Vrba wrote:
| Quote: | Are we allowed to return lambdas from functions? Store them in variables? What
if lambda references existing local variables?
|
It's clear, at least to me, that C++ lambdas should obey
the normal restrictions on automatic variables, which is
that pointers and references to them cannot outlast their
lifetime. Even so, they're exteremly useful.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|